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 ¶
- Variables
- func AddRecoveryKey(st *state.State, recoveryKeyID string, keyslotRefs []KeyslotRef) (*state.TaskSet, error)
- func AttemptAutoRepairIfNeeded(st *state.State, lockoutResetErr error) error
- func ChangeAuth(st *state.State, authMode device.AuthMode, old, new string, ...) (*state.TaskSet, error)
- func EFISecurebootDBManagerStartup(st *state.State) error
- func EFISecurebootDBUpdateCleanup(st *state.State) error
- func EFISecurebootDBUpdatePrepare(st *state.State, db EFISecurebootKeyDatabase, payloads [][]byte) error
- func GenerateRecoveryKey(st *state.State) (rkey keys.RecoveryKey, keyID string, err error)
- func GetKeyslots(st *state.State, keyslotRefs []KeyslotRef) (keyslots []Keyslot, missingRefs []KeyslotRef, err error)
- func GetRecoveryKey(st *state.State, keyID string) (rkey keys.RecoveryKey, err error)
- func MockDisksDMCryptUUIDFromMountPoint(f func(mountpoint string) (string, error)) (restore func())
- func MockGetPrimaryKeyDigest(f func(devicePath string, alg crypto.Hash) ([]byte, []byte, error)) (restore func())
- func MockKeyslotKeyData(keyslot *Keyslot, kd secboot.KeyData)
- func MockSecbootGetPCRHandle(...) (restore func())
- func MockVerifyPrimaryKeyDigest(...) (restore func())
- func ReplacePlatformKey(st *state.State, volumesAuth *device.VolumesAuthOptions, ...) (*state.TaskSet, error)
- func ReplaceRecoveryKey(st *state.State, recoveryKeyID string, keyslotRefs []KeyslotRef) (*state.TaskSet, error)
- func RunningWithPlatformKeys(status FDEStatus) bool
- func SystemEncryptedFromState(st *state.State) (bool, error)
- type AutoRepairResult
- type EFISecurebootKeyDatabase
- type ExternalOperationStatus
- type FDEManager
- func (m *FDEManager) CheckRecoveryKey(rkey keys.RecoveryKey, containerRoles []string) error
- func (m *FDEManager) DeviceInitialized()
- func (m *FDEManager) Ensure() error
- func (m *FDEManager) GenerateRecoveryKey() (rkey keys.RecoveryKey, keyID string, err error)
- func (m *FDEManager) GetEncryptedContainers() ([]backend.EncryptedContainer, error)
- func (m *FDEManager) GetKeyslots(keyslotRefs []KeyslotRef) (keyslots []Keyslot, missingRefs []KeyslotRef, err error)
- func (m *FDEManager) GetParameters(role string, containerRole string) (roleParams *backend.SealingParameters, err error)
- func (m *FDEManager) GetRoleInfo(role string) (roleInfo *backend.RoleInfo, err error)
- func (m *FDEManager) NextUniqueKeyslot(containerRole, prefix string) (ref KeyslotRef, err error)
- func (m *FDEManager) Reinitialize()
- func (m *FDEManager) ReloadModeenv() error
- func (m *FDEManager) UpdateParameters(role string, containerRole string, bootModes []string, ...) error
- func (m *FDEManager) VerifyPrimaryKeyAgainstState(primaryKeyID int, primaryKey []byte) bool
- type FDEStatus
- type FDESystemState
- type FdeState
- type InsufficientContainerCapacityError
- type InvalidRecoveryKeyError
- type InvalidRecoveryKeyReason
- type KeyDigest
- type Keyslot
- type KeyslotRef
- type KeyslotRefsNotFoundError
- type KeyslotRoleInfo
- type KeyslotRoleParameters
- type KeyslotType
- type KeyslotsAlreadyExistsError
- type Model
- type PrimaryKeyInfo
Constants ¶
This section is empty.
Variables ¶
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 ¶
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 ¶
EFISecurebootDBManagerStartup indicates that the local EFI key database manager has started.
func EFISecurebootDBUpdateCleanup ¶
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 ¶
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 ¶
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 MockGetPrimaryKeyDigest ¶
func MockKeyslotKeyData ¶
func MockSecbootGetPCRHandle ¶
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 ¶
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 ¶
func (e *InsufficientContainerCapacityError) Error() string
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 ¶
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 ¶
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 ¶
func (e *KeyslotsAlreadyExistsError) Error() string
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) Grade ¶
func (m *Model) Grade() asserts.ModelGrade
Grade implements secboot.ModelForSealing.Grade
type PrimaryKeyInfo ¶
type PrimaryKeyInfo struct {
Digest KeyDigest `json:"digest"`
}
PrimaryKeyInfo provides information about a primary key that is used to manage key slots