Skip to content

Commit

Permalink
feat: provide an option to enforce SecureBoot for TPM enrollment
Browse files Browse the repository at this point in the history
Fixes siderolabs#8995

There is no security impact, as the actual SecureBoot
state/configuration is measured into the PCR 7 and the disk encryption
key unsealing is tied to this value.

This is more to provide a way to avoid accidentally encrypting to the
TPM while SecureBoot is not enabled.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
  • Loading branch information
smira committed Jul 11, 2024
1 parent 398151e commit 78aaf61
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 8 deletions.
4 changes: 3 additions & 1 deletion cmd/talosctl/cmd/mgmt/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,9 @@ func create(ctx context.Context) error {
provisionOptions = append(provisionOptions, provision.WithKMS(nethelpers.JoinHostPort("0.0.0.0", port)))
case "tpm":
keys = append(keys, &v1alpha1.EncryptionKey{
KeyTPM: &v1alpha1.EncryptionKeyTPM{},
KeyTPM: &v1alpha1.EncryptionKeyTPM{
TPMCheckSecurebootStatusOnEnroll: pointer.To(true),
},
KeySlot: i,
})
default:
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/encryption/keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func NewHandler(cfg config.EncryptionKey, options ...KeyOption) (Handler, error)

return NewKMSKeyHandler(key, cfg.KMS().Endpoint(), opts.GetSystemInformation)
case cfg.TPM() != nil:
return NewTPMKeyHandler(key)
return NewTPMKeyHandler(key, cfg.TPM().CheckSecurebootOnEnroll())
}

return nil, errors.New("malformed config: no key handler can be created")
Expand Down
19 changes: 17 additions & 2 deletions internal/pkg/encryption/keys/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"io"

"github.com/foxboron/go-uefi/efi"
"github.com/siderolabs/go-blockdevice/blockdevice/encryption"
"github.com/siderolabs/go-blockdevice/blockdevice/encryption/luks"
"github.com/siderolabs/go-blockdevice/blockdevice/encryption/token"
Expand All @@ -32,17 +34,30 @@ type TPMToken struct {
// TPMKeyHandler seals token using TPM.
type TPMKeyHandler struct {
KeyHandler

checkSecurebootOnEnroll bool
}

// NewTPMKeyHandler creates new TPMKeyHandler.
func NewTPMKeyHandler(key KeyHandler) (*TPMKeyHandler, error) {
func NewTPMKeyHandler(key KeyHandler, checkSecurebootOnEnroll bool) (*TPMKeyHandler, error) {
return &TPMKeyHandler{
KeyHandler: key,
KeyHandler: key,
checkSecurebootOnEnroll: checkSecurebootOnEnroll,
}, nil
}

// NewKey implements Handler interface.
func (h *TPMKeyHandler) NewKey(ctx context.Context) (*encryption.Key, token.Token, error) {
if h.checkSecurebootOnEnroll {
if !efi.GetSecureBoot() {
return nil, nil, fmt.Errorf("failed to enroll the TPM2 key, as SecureBoot is disabled")
}

if efi.GetSetupMode() {
return nil, nil, fmt.Errorf("failed to enroll the TPM2 key, as the system is in setup mode")
}
}

key := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
return nil, nil, err
Expand Down
1 change: 1 addition & 0 deletions pkg/machinery/config/config/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ type EncryptionKeyNodeID interface {

// EncryptionKeyTPM encryption key sealed by TPM.
type EncryptionKeyTPM interface {
CheckSecurebootOnEnroll() bool
String() string
}

Expand Down
10 changes: 9 additions & 1 deletion pkg/machinery/config/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,15 @@
"type": "object"
},
"v1alpha1.EncryptionKeyTPM": {
"properties": {},
"properties": {
"checkSecurebootStatusOnEnroll": {
"type": "boolean",
"title": "checkSecurebootStatusOnEnroll",
"description": "description: \u0026gt;\n Check that Secureboot is enabled in the EFI firmware.\n\nIf Secureboot is not enabled, the enrollment of the key will fail.\n\n\nAs the TPM key is anyways bound to the value of PCR 7,\n changing Secureboot status or configuration\n after the initial enrollment will make the key unusable.\n",
"markdownDescription": "description: \u003e\n Check that Secureboot is enabled in the EFI firmware.\n\n If Secureboot is not enabled, the enrollment of the key will fail.\n As the TPM key is anyways bound to the value of PCR 7,\n changing Secureboot status or configuration\n after the initial enrollment will make the key unusable.",
"x-intellij-html-description": "\u003cp\u003edescription: \u0026gt;\n Check that Secureboot is enabled in the EFI firmware.\u003c/p\u003e\n\n\u003cpre\u003e\u003ccode\u003eIf Secureboot is not enabled, the enrollment of the key will fail.\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eAs the TPM key is anyways bound to the value of PCR 7,\n changing Secureboot status or configuration\n after the initial enrollment will make the key unusable.\u003c/p\u003e\n"
}
},
"additionalProperties": false,
"type": "object"
},
Expand Down
9 changes: 9 additions & 0 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,15 @@ func (e *EncryptionKeyTPM) String() string {
return "tpm"
}

// CheckSecurebootOnEnroll implements the config.Provider interface.
func (e *EncryptionKeyTPM) CheckSecurebootOnEnroll() bool {
if e == nil {
return false
}

return pointer.SafeDeref(e.TPMCheckSecurebootStatusOnEnroll)
}

// Slot implements the config.Provider interface.
func (e *EncryptionKey) Slot() int {
return e.KeySlot
Expand Down
11 changes: 10 additions & 1 deletion pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1621,7 +1621,16 @@ type EncryptionKeyKMS struct {
}

// EncryptionKeyTPM represents a key that is generated and then sealed/unsealed by the TPM.
type EncryptionKeyTPM struct{}
type EncryptionKeyTPM struct {
// description: >
// Check that Secureboot is enabled in the EFI firmware.
//
// If Secureboot is not enabled, the enrollment of the key will fail.
// As the TPM key is anyways bound to the value of PCR 7,
// changing Secureboot status or configuration
// after the initial enrollment will make the key unusable.
TPMCheckSecurebootStatusOnEnroll *bool `yaml:"checkSecurebootStatusOnEnroll,omitempty"`
}

// EncryptionKeyNodeID represents deterministically generated key from the node UUID and PartitionLabel.
type EncryptionKeyNodeID struct{}
Expand Down
10 changes: 9 additions & 1 deletion pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2397,6 +2397,10 @@ EncryptionKeyTPM represents a key that is generated and then sealed/unsealed by



| Field | Type | Description | Value(s) |
|-------|------|-------------|----------|
|`checkSecurebootStatusOnEnroll` |bool |<details><summary>description: ></summary> Check that Secureboot is enabled in the EFI firmware.<br /><br /> If Secureboot is not enabled, the enrollment of the key will fail.<br /> As the TPM key is anyways bound to the value of PCR 7,<br /> changing Secureboot status or configuration<br /> after the initial enrollment will make the key unusable.<br /></details> | |




Expand Down Expand Up @@ -2516,6 +2520,10 @@ EncryptionKeyTPM represents a key that is generated and then sealed/unsealed by



| Field | Type | Description | Value(s) |
|-------|------|-------------|----------|
|`checkSecurebootStatusOnEnroll` |bool |<details><summary>description: ></summary> Check that Secureboot is enabled in the EFI firmware.<br /><br /> If Secureboot is not enabled, the enrollment of the key will fail.<br /> As the TPM key is anyways bound to the value of PCR 7,<br /> changing Secureboot status or configuration<br /> after the initial enrollment will make the key unusable.<br /></details> | |




Expand Down
10 changes: 9 additions & 1 deletion website/content/v1.8/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,15 @@
"type": "object"
},
"v1alpha1.EncryptionKeyTPM": {
"properties": {},
"properties": {
"checkSecurebootStatusOnEnroll": {
"type": "boolean",
"title": "checkSecurebootStatusOnEnroll",
"description": "description: \u0026gt;\n Check that Secureboot is enabled in the EFI firmware.\n\nIf Secureboot is not enabled, the enrollment of the key will fail.\n\n\nAs the TPM key is anyways bound to the value of PCR 7,\n changing Secureboot status or configuration\n after the initial enrollment will make the key unusable.\n",
"markdownDescription": "description: \u003e\n Check that Secureboot is enabled in the EFI firmware.\n\n If Secureboot is not enabled, the enrollment of the key will fail.\n As the TPM key is anyways bound to the value of PCR 7,\n changing Secureboot status or configuration\n after the initial enrollment will make the key unusable.",
"x-intellij-html-description": "\u003cp\u003edescription: \u0026gt;\n Check that Secureboot is enabled in the EFI firmware.\u003c/p\u003e\n\n\u003cpre\u003e\u003ccode\u003eIf Secureboot is not enabled, the enrollment of the key will fail.\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eAs the TPM key is anyways bound to the value of PCR 7,\n changing Secureboot status or configuration\n after the initial enrollment will make the key unusable.\u003c/p\u003e\n"
}
},
"additionalProperties": false,
"type": "object"
},
Expand Down

0 comments on commit 78aaf61

Please sign in to comment.