Skip to content

Commit

Permalink
Set device to maintenance mode if TPM error is detected
Browse files Browse the repository at this point in the history
We have seen errors like "point is not on the required curve" in the
past that prevents the device from upgrading because TPM fails to perform
an ECDH key agreement to generate the KEK and decrypt the vault key.
To catch these errors early, check if TPM is not functioning properly on
a critical path and set the device to maintenance mode.

Signed-off-by: Shahriyar Jalayeri <shahriyar@zededa.com>
  • Loading branch information
shjala committed Dec 11, 2024
1 parent e872c81 commit 4b184ce
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 4 deletions.
16 changes: 12 additions & 4 deletions pkg/pillar/cmd/vaultmgr/vaultmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,13 +512,21 @@ func publishVaultKey(ctx *vaultMgrContext, vaultName string) error {
}
keyBytes, err := etpm.FetchSealedVaultKey(log)
if err != nil {
return fmt.Errorf("Failed to retrieve key from TPM %w", err)
return fmt.Errorf("failed to retrieve key from TPM %w", err)
}

encryptedKey, err := etpm.EncryptDecryptUsingTpm(keyBytes, true)
if err != nil {
// XXX should we still send with no key?
return fmt.Errorf("Failed to encrypt vault key %w", err)
// if we can't encrypt the vault key using TPM, possibly something
// is horribly wrong with TPM, this can bite us later for example
// when we try to upgrade the device, so better to fail early.
key := types.EncryptedVaultKeyFromDevice{
Name: vaultName,
TpmError: err}
ctx.pubVaultKeyFromDevice.Publish(key.Key(), key)

// still return error, this will get logged
return fmt.Errorf("failed to encrypt vault key %w", err)
}

hash := sha256.New()
Expand All @@ -531,7 +539,7 @@ func publishVaultKey(ctx *vaultMgrContext, vaultName string) error {
}
encryptedVaultKey, err = proto.Marshal(keyData)
if err != nil {
return fmt.Errorf("Failed to Marshal keyData %w", err)
return fmt.Errorf("failed to Marshal keyData %w", err)
}
}

Expand Down
7 changes: 7 additions & 0 deletions pkg/pillar/cmd/zedagent/attesttask.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,13 @@ func handleEncryptedKeyFromDeviceImpl(ctxArg interface{}, key string,
log.Noticef("handleEncryptedKeyFromDeviceImpl len %d",
len(vaultKey.EncryptedVaultKey))

if vaultKey.TpmError != nil {
ctx.maintenanceMode = true
ctx.maintModeReason = types.MaintenanceModeReasonTpmFailure
log.Errorf("setting maintenance mode due to TPM failurec: %v", vaultKey.TpmError)
return
}

if ctx.attestCtx == nil {
log.Fatalf("[ATTEST] Uninitialized access to attestCtx")
}
Expand Down
1 change: 1 addition & 0 deletions pkg/pillar/types/vaultmgrtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type EncryptedVaultKeyFromDevice struct {
Name string
EncryptedVaultKey []byte // empty if no TPM enabled
IsTpmEnabled bool
TpmError error // only set if there is unrecoverable error, for example TPM is kaputt.
}

// Key returns name of the vault corresponding to this object
Expand Down
3 changes: 3 additions & 0 deletions pkg/pillar/types/zedagenttypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ const (
MaintenanceModeReasonUserRequested
MaintenanceModeReasonVaultLockedUp
MaintenanceModeReasonNoDiskSpace
MaintenanceModeReasonTpmFailure
)

// String returns the verbose equivalent of MaintenanceModeReason code
Expand All @@ -408,6 +409,8 @@ func (mmr MaintenanceModeReason) String() string {
return "MaintenanceModeReasonVaultLockedUp"
case MaintenanceModeReasonNoDiskSpace:
return "MaintenanceModeReasonNoDiskSpace"
case MaintenanceModeReasonTpmFailure:
return "MaintenanceModeReasonTpmFailure"
default:
return fmt.Sprintf("Unknown MaintenanceModeReason %d", mmr)
}
Expand Down

0 comments on commit 4b184ce

Please sign in to comment.