fdestate

package
v0.0.0-...-b5866da Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2026 License: GPL-3.0 Imports: 27 Imported by: 0

Documentation

Overview

  • 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 <http://www.gnu.org/licenses/>. *

  • Copyright (C) 2025 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 <http://www.gnu.org/licenses/>. *

  • Copyright (C) 2025 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 <http://www.gnu.org/licenses/>. *

  • 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 <http://www.gnu.org/licenses/>. *

Package fdestate implements the manager and state responsible for managing full disk encryption keys.

  • 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 <http://www.gnu.org/licenses/>. *

  • Copyright (C) 2025 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 <http://www.gnu.org/licenses/>. *

  • 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 <http://www.gnu.org/licenses/>. *

Index

Constants

This section is empty.

Variables

View Source
var ErrNotInitialized = errors.New("fde state was not initialized")

Functions

func AddRecoveryKey

func AddRecoveryKey(st *state.State, recoveryKeyID string, keyslotRefs []KeyslotRef) (*state.TaskSet, error)

AddRecoveryKey creates a taskset that adds a recovery key for the specified target key slots using the recovery key identified by recoveryKeyID.

If the recovery key ID is invalid, an InvalidRecoveryKeyError is returned.

If any key slot from keyslotRefs already exists, a KeyslotsAlreadyExistsError is returned.

If some target container has insufficient capacity, an InsufficientContainerCapacity is returned.

func AttemptAutoRepairIfNeeded

func AttemptAutoRepairIfNeeded(st *state.State, lockoutResetErr error) error

AttemptAutoRepairIfNeeded looks at the activation state and status of lockout reset and may attempt to repair keyslots. If the auto-repair attempted has already occurred during the current boot, this will do nothing.

func ChangeAuth

func ChangeAuth(st *state.State, authMode device.AuthMode, old, new string, keyslotRefs []KeyslotRef) (*state.TaskSet, error)

ChangeAuth creates a taskset that changes the PIN or passphrase for the specified target key slots.

If keyslotRefs is empty, the following key slots are targets:

  • container-role: system-data, name: default
  • container-role: system-data, name: default-fallback
  • container-role: system-save, name: default-fallback

func EFISecurebootDBManagerStartup

func EFISecurebootDBManagerStartup(st *state.State) error

EFISecurebootDBManagerStartup indicates that the local EFI key database manager has started.

func EFISecurebootDBUpdateCleanup

func EFISecurebootDBUpdateCleanup(st *state.State) error

EFISecurebootDBUpdateCleanup notifies that the local EFI key database manager has reached a cleanup stage of the update process.

func EFISecurebootDBUpdatePrepare

func EFISecurebootDBUpdatePrepare(st *state.State, db EFISecurebootKeyDatabase, payloads [][]byte) error

EFISecurebootDBUpdatePrepare notifies that the local EFI key database manager is about to update the database.

func GenerateRecoveryKey

func GenerateRecoveryKey(st *state.State) (rkey keys.RecoveryKey, keyID string, err error)

GenerateRecoveryKey generates a recovery key and its corresponding id with an expiration time `recoveryKeyExpireAfter`.

The state needs to be locked by the caller.

func GetKeyslots

func GetKeyslots(st *state.State, keyslotRefs []KeyslotRef) (keyslots []Keyslot, missingRefs []KeyslotRef, err error)

GetKeyslots returns the key slots for the specified key slot references. If keyslotRefs is empty, all key slots on all encrypted containers will be returned.

The state needs to be locked by the caller.

func GetRecoveryKey

func GetRecoveryKey(st *state.State, keyID string) (rkey keys.RecoveryKey, err error)

GetRecoveryKey retrieves a recovery key by its key-id. The key can only be retrieved once and is immediately deleted after being retrieved. An error is returned if the corresponding recovery key is expired.

The state needs to be locked by the caller.

func MockDisksDMCryptUUIDFromMountPoint

func MockDisksDMCryptUUIDFromMountPoint(f func(mountpoint string) (string, error)) (restore func())

func MockGetPrimaryKeyDigest

func MockGetPrimaryKeyDigest(f func(devicePath string, alg crypto.Hash) ([]byte, []byte, error)) (restore func())

func MockKeyslotKeyData

func MockKeyslotKeyData(keyslot *Keyslot, kd secboot.KeyData)

func MockSecbootGetPCRHandle

func MockSecbootGetPCRHandle(f func(devicePath, keySlot, keyFile string, hintExpectFDEHook bool) (uint32, error)) (restore func())

func MockVerifyPrimaryKeyDigest

func MockVerifyPrimaryKeyDigest(f func(devicePath string, alg crypto.Hash, salt []byte, digest []byte) (bool, error)) (restore func())

func ReplacePlatformKey

func ReplacePlatformKey(st *state.State, volumesAuth *device.VolumesAuthOptions, keyslotRefs []KeyslotRef) (*state.TaskSet, error)

ReplacePlatformKey creates a taskset that replaces the platform protected key for the specified target key slots.

If keyslotRefs is empty, the following key slots are targets:

  • container-role: system-data, name: default
  • container-role: system-data, name: default-fallback
  • container-role: system-save, name: default-fallback

func ReplaceRecoveryKey

func ReplaceRecoveryKey(st *state.State, recoveryKeyID string, keyslotRefs []KeyslotRef) (*state.TaskSet, error)

ReplaceRecoveryKey creates a taskset that replaces the recovery key for the specified target key slots using the recovery key identified by recoveryKeyID.

If keyslotRefs is empty, the "default-recovery" key slot is used by default for both the "system-data" and "system-save" container roles.

If the recovery key ID is invalid, an InvalidRecoveryKeyError is returned.

If any key slot from keyslotRefs does not exist, a KeyslotRefsNotFoundError is returned.

func RunningWithPlatformKeys

func RunningWithPlatformKeys(status FDEStatus) bool

func SystemEncryptedFromState

func SystemEncryptedFromState(st *state.State) (bool, error)

SystemEncryptedFromState reports whether FDE is enabled on the system. It returns true if FDE is enabled, or false otherwise.

Types

type AutoRepairResult

type AutoRepairResult string
const (
	AutoRepairNotInitialized          AutoRepairResult = "not-initialized"
	AutoRepairNotAttempted            AutoRepairResult = "not-attempted"
	AutoRepairFailedPlatformInit      AutoRepairResult = "failed-platform-init"
	AutoRepairFailedKeyslots          AutoRepairResult = "failed-keyslots"
	AutoRepairFailedEncryptionSupport AutoRepairResult = "failed-encryption-support"
	AutoRepairSuccess                 AutoRepairResult = "success"
)

type EFISecurebootKeyDatabase

type EFISecurebootKeyDatabase int
const (
	EFISecurebootPK EFISecurebootKeyDatabase = iota
	EFISecurebootKEK
	EFISecurebootDB
	EFISecurebootDBX
)

func (EFISecurebootKeyDatabase) String

func (db EFISecurebootKeyDatabase) String() string

type ExternalOperationStatus

type ExternalOperationStatus int

ExternalOperationStatus captures the status of operations running externally.

const (
	DefaultStatus ExternalOperationStatus = 0

	// Preparing means that we are performing preparation steps, but the
	// operation isn't yet running externally.
	PreparingStatus ExternalOperationStatus = 1

	// DoingStatus means the operation is running externally.
	DoingStatus ExternalOperationStatus = 2

	// DoneStatus means the operation has completed successfully. Done status is
	// final.
	DoneStatus ExternalOperationStatus = 3

	// CompletingStatus means the operation is completing.
	CompletingStatus ExternalOperationStatus = 4

	// AbortingStatus means the operation is aborting.
	AbortingStatus ExternalOperationStatus = 5

	// ErrorStatus means the operation has failed. Error status is final.
	ErrorStatus ExternalOperationStatus = 6
)

Admitted status values for changes and tasks. The expected use of status is shown in a diagram below:

        Default
           |
           v
       Preparing
           | |
           v +---------+
         Doing         |
           |           |
    +------+-----+     |
    v            v     |
Completing   Aborting  |
   | |           |     |
   | |           |     |
   | +-----------+-----+
   |             |
   v             v
 Done          Error

The Done and Error statuses are considered to be final. A newly created operation should be assigned a Preparing status and then Doing after. Doing is where the operation is running externally. Once notified about status change, the status should be changed to Completing or Aborting, proceeded by one of the final statues. The statuses Preparing, Completing, Aborting, are useful when an intermediate step is needed for properly blocking conflicting API calls, where a state is internally unlocked, eg. when resealing.

func (ExternalOperationStatus) String

func (s ExternalOperationStatus) String() string

type FDEManager

type FDEManager struct {
	// contains filtered or unexported fields
}

FDEManager is responsible for managing full disk encryption keys.

func Manager

func Manager(st *state.State, runner *state.TaskRunner) (*FDEManager, error)

func (*FDEManager) CheckRecoveryKey

func (m *FDEManager) CheckRecoveryKey(rkey keys.RecoveryKey, containerRoles []string) error

CheckRecoveryKey tests that the specified recovery key unlocks the specified container roles. If containerRoles is empty, the recovery key will be tested against all container roles. Also, If a container role from containerRoles does not exist, an error is returned.

The state must be locked by the caller.

func (*FDEManager) DeviceInitialized

func (m *FDEManager) DeviceInitialized()

TODO: move this back to StartUp once we have StartUp dependencies.

func (*FDEManager) Ensure

func (m *FDEManager) Ensure() error

Ensure implements StateManager.Ensure

func (*FDEManager) GenerateRecoveryKey

func (m *FDEManager) GenerateRecoveryKey() (rkey keys.RecoveryKey, keyID string, err error)

GenerateRecoveryKey generates a recovery key and its corresponding id with an expiration time `recoveryKeyExpireAfter`.

func (*FDEManager) GetEncryptedContainers

func (m *FDEManager) GetEncryptedContainers() ([]backend.EncryptedContainer, error)

GetEncryptedContainers returns the encrypted disks with their keys for the current device. The list of encrypted disks has no specific order.

func (*FDEManager) GetKeyslots

func (m *FDEManager) GetKeyslots(keyslotRefs []KeyslotRef) (keyslots []Keyslot, missingRefs []KeyslotRef, err error)

GetKeyslots returns the key slots for the specified key slot references. If keyslotRefs is empty, all key slots on all encrypted containers will be returned.

func (*FDEManager) GetParameters

func (m *FDEManager) GetParameters(role string, containerRole string) (roleParams *backend.SealingParameters, err error)

func (*FDEManager) GetRoleInfo

func (m *FDEManager) GetRoleInfo(role string) (roleInfo *backend.RoleInfo, err error)

func (*FDEManager) NextUniqueKeyslot

func (m *FDEManager) NextUniqueKeyslot(containerRole, prefix string) (ref KeyslotRef, err error)

NextUniqueKeyslot returns a unique keyslot reference given a container role and a prefix which can be used for conflict free ephemeral key names. This can be used for temporary key names during key replacement or re-provisioning. The returned keyslot is only unique within the specified container and is formatted as `<prefix>-XX`.

The state needs to be locked by the caller.

func (*FDEManager) Reinitialize

func (m *FDEManager) Reinitialize()

func (*FDEManager) ReloadModeenv

func (m *FDEManager) ReloadModeenv() error

ReloadModeenv is a helper function for forcing a reload of modeenv. Only useful in integration testing.

func (*FDEManager) UpdateParameters

func (m *FDEManager) UpdateParameters(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error

func (*FDEManager) VerifyPrimaryKeyAgainstState

func (m *FDEManager) VerifyPrimaryKeyAgainstState(primaryKeyID int, primaryKey []byte) bool

VerifyPrimaryKeyAgainstState takes a primary key ID and verifies the digest associated to that primary key ID in the state matches the given primary key

type FDEStatus

type FDEStatus string
const (
	// FDEStatusIndeterminate means we had an error while detecting
	// the current status. This will happen if the kernel snap is
	// too old, or we used a non-snap kernel (classic).
	FDEStatusIndeterminate FDEStatus = "indeterminate"
	// FDEStatusActive means disks have been activated and no
	// recovery key was used.
	FDEStatusActive FDEStatus = "active"
	// FDEStatusInactive means no encrypted disk has been
	// activated.
	FDEStatusInactive FDEStatus = "inactive"
	// FDEStatusRecovery means some disk have been activated with
	// a recovery key.
	FDEStatusRecovery FDEStatus = "recovery"
	// FDEStatusDegraded is reported when otherwise active, some
	// keyslots tried were invalid.
	FDEStatusDegraded FDEStatus = "degraded"
)

type FDESystemState

type FDESystemState struct {
	// Status gives a summary on whether encrypted disks have been
	// activated and whether any recovery key was used.
	Status FDEStatus `json:"status"`

	// AutoRepairResult is the status of the auto-repair attempt
	AutoRepairResult AutoRepairResult `json:"auto-repair-result"`
}

FDESystemState is json serializable disk encryption state for the current boot.

func SystemState

func SystemState(st *state.State) (*FDESystemState, error)

SystemState returns a json serializable FDE state of the booted system.

type FdeState

type FdeState struct {
	// PrimaryKeys are the keys on the system. Key with ID 0 is
	// reserved for snapd and is populated on first boot. Other
	// IDs are for externally managed keys.
	// If key 0 is not present, we are on a legacy system that
	// does not have a primary key. We are then in one of these cases:
	//  * v1 TPM keys are in used because an old snapd was used
	//    during installation.
	//  * snap-bootstrap in the kernel is old and does not provide
	//    a primary key in the keyring.
	PrimaryKeys map[int]PrimaryKeyInfo `json:"primary-keys"`

	// KeyslotRoles are all keyslot roles indexed by the role name
	KeyslotRoles map[string]KeyslotRoleInfo `json:"keyslot-roles"`

	// PendingExternalOperations keeps a list of changes that capture FDE
	// related operations running outside of snapd.
	PendingExternalOperations []externalOperation `json:"pending-external-operations"`
}

FdeState is the root persistent FDE state

type InsufficientContainerCapacityError

type InsufficientContainerCapacityError struct {
	ContainerRoles []string
}

func (*InsufficientContainerCapacityError) Error

type InvalidRecoveryKeyError

type InvalidRecoveryKeyError struct {
	Reason InvalidRecoveryKeyReason

	Message string
}

func (*InvalidRecoveryKeyError) Error

func (e *InvalidRecoveryKeyError) Error() string

type InvalidRecoveryKeyReason

type InvalidRecoveryKeyReason string
const (
	InvalidRecoveryKeyReasonExpired       InvalidRecoveryKeyReason = "expired"
	InvalidRecoveryKeyReasonNotFound      InvalidRecoveryKeyReason = "not-found"
	InvalidRecoveryKeyReasonInvalidFormat InvalidRecoveryKeyReason = "invalid-format"
	InvalidRecoveryKeyReasonInvalidValue  InvalidRecoveryKeyReason = "invalid-value"
)

type KeyDigest

type KeyDigest struct {
	// Algorithm is the algorithm for
	Algorithm secboot.HashAlg `json:"alg"`
	// Salt is the salt for the Digest digest
	Salt []byte `json:"salt"`
	// Digest is the result of `Digest(key, salt)`
	Digest []byte `json:"digest"`
}

KeyDigest stores a Digest(key, salt) of a key TODO:FDEM: take what is implemented in secboot

type Keyslot

type Keyslot struct {
	// The unique key slot name on the corresponding encrypted container.
	Name string
	// This indicates whether this is a recovery or platform protected key.
	Type KeyslotType
	// This indicates the container role of the corresponding encrypted container.
	ContainerRole string
	// contains filtered or unexported fields
}

Keyslot represents a key associated with an encrypted container.

func (*Keyslot) KeyData

func (k *Keyslot) KeyData() (secboot.KeyData, error)

KeyData returns secboot.KeyData corresponding to the keyslot. This can only be called for KeyslotTypePlatform.

Note: KeyData is lazy loaded once then reused in subsequent calls.

func (*Keyslot) Ref

func (k *Keyslot) Ref() KeyslotRef

Ref returns the corresponding key slot reference.

type KeyslotRef

type KeyslotRef struct {
	Name          string `json:"name"`
	ContainerRole string `json:"container-role"`
}

KeyslotRef uniquely identifies a target key slot by its container role and name.

func ExpandSystemContainerRoles

func ExpandSystemContainerRoles(keyslotName string) []KeyslotRef

ExpandSystemContainerRoles expands the given key slot name into a list of key slot references for default system container roles i.e. [system-data, system-save].

func (KeyslotRef) String

func (k KeyslotRef) String() string

func (KeyslotRef) Validate

func (k KeyslotRef) Validate(keyslotType KeyslotType) error

Validate that the key slot reference points to expected key slots.

type KeyslotRefsNotFoundError

type KeyslotRefsNotFoundError struct {
	KeyslotRefs []KeyslotRef
}

func (*KeyslotRefsNotFoundError) Error

func (e *KeyslotRefsNotFoundError) Error() string

type KeyslotRoleInfo

type KeyslotRoleInfo struct {
	// PrimaryKeyID is the ID for the primary key found in
	// PrimaryKeys field of FdeState
	PrimaryKeyID int `json:"primary-key-id"`
	// Parameters is indexed by container role name
	Parameters map[string]KeyslotRoleParameters `json:"params,omitempty"`
	// TPM2PCRPolicyRevocationCounter is the handle for the TPM
	// policy revocation counter.  A value of 0 means it is not
	// set.
	TPM2PCRPolicyRevocationCounter uint32 `json:"tpm2-pcr-policy-revocation-counter,omitempty"`
}

KeyslotRoleInfo stores information about a key slot role

type KeyslotRoleParameters

type KeyslotRoleParameters struct {
	// Models are the optional list of approved models
	Models []*Model `json:"models,omitempty"`
	// BootModes are the optional list of approved modes (run, recover, ...)
	BootModes []string `json:"boot-modes,omitempty"`
	// TPM2PCRProfile is an optional serialized PCR profile
	TPM2PCRProfile secboot.SerializedPCRProfile `json:"tpm2-pcr-profile,omitempty"`
}

KeyslotRoleParameters stores upgradeable parameters for a keyslot role

type KeyslotType

type KeyslotType string
const (
	KeyslotTypeRecovery KeyslotType = "recovery"
	KeyslotTypePlatform KeyslotType = "platform"
)

type KeyslotsAlreadyExistsError

type KeyslotsAlreadyExistsError struct {
	Keyslots []Keyslot
}

func (*KeyslotsAlreadyExistsError) Error

type Model

type Model struct {
	SeriesValue    string             `json:"series"`
	BrandIDValue   string             `json:"brand-id"`
	ModelValue     string             `json:"model"`
	ClassicValue   bool               `json:"classic"`
	GradeValue     asserts.ModelGrade `json:"grade"`
	SignKeyIDValue string             `json:"sign-key-id"`
}

Model is a json serializable secboot.ModelForSealing

func (*Model) BrandID

func (m *Model) BrandID() string

BrandID implements secboot.ModelForSealing.BrandID

func (*Model) Classic

func (m *Model) Classic() bool

Classic implements secboot.ModelForSealing.Classic

func (*Model) Grade

func (m *Model) Grade() asserts.ModelGrade

Grade implements secboot.ModelForSealing.Grade

func (*Model) Model

func (m *Model) Model() string

Model implements secboot.ModelForSealing.Model

func (*Model) Series

func (m *Model) Series() string

Series implements secboot.ModelForSealing.Series

func (*Model) SignKeyID

func (m *Model) SignKeyID() string

SignKeyID implements secboot.ModelForSealing.SignKeyID

type PrimaryKeyInfo

type PrimaryKeyInfo struct {
	Digest KeyDigest `json:"digest"`
}

PrimaryKeyInfo provides information about a primary key that is used to manage key slots

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL