metropolis/node: fix non-secure TPM/storage policy codepaths

This fixes enoug things to pass manually ran E2E tests with the initial
cluster confiugration changed to a number of possible combinations
(with/without TPM, with authenticated/encrypted/insecure storage).

These should, of course, be automatically tested. However, that is
pending on the extension of E2E test system that will let it run
long-term tests against real clusters. Otherwise we'd just waste tons of
time running the entire matrix of possible combinations on every CR.

Change-Id: I71a56f9a31c738ee2b2d4dfa10d2a58fd5cb0554
Reviewed-on: https://review.monogon.dev/c/monogon/+/1810
Tested-by: Jenkins CI
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
diff --git a/metropolis/node/core/cluster/cluster.go b/metropolis/node/core/cluster/cluster.go
index 529120b..9cc3f6b 100644
--- a/metropolis/node/core/cluster/cluster.go
+++ b/metropolis/node/core/cluster/cluster.go
@@ -74,7 +74,7 @@
 	close(m.oneway)
 
 	// Try sealed configuration first.
-	configuration, err := m.storageRoot.ESP.Metropolis.SealedConfiguration.Unseal()
+	configuration, err := m.storageRoot.ESP.Metropolis.SealedConfiguration.Unseal(cpb.NodeTPMUsage_NODE_TPM_PRESENT_AND_USED)
 	if err == nil {
 		supervisor.Logger(ctx).Info("Sealed configuration present. attempting to join cluster")
 
@@ -88,11 +88,11 @@
 		return m.join(ctx, configuration, cd, true)
 	}
 
-	if !errors.Is(err, localstorage.ErrNoSealed) {
+	if !errors.Is(err, localstorage.ErrNoSealed) && !errors.Is(err, localstorage.ErrSealedCorrupted) {
 		return fmt.Errorf("unexpected sealed config error: %w", err)
 	}
 
-	configuration, err = m.storageRoot.ESP.Metropolis.SealedConfiguration.ReadUnsafe()
+	configuration, err = m.storageRoot.ESP.Metropolis.SealedConfiguration.Unseal(cpb.NodeTPMUsage_NODE_TPM_NOT_PRESENT)
 	if err == nil {
 		supervisor.Logger(ctx).Info("Non-sealed configuration present. attempting to join cluster")
 
diff --git a/metropolis/node/core/localstorage/directory_data.go b/metropolis/node/core/localstorage/directory_data.go
index c255089..5607e0a 100644
--- a/metropolis/node/core/localstorage/directory_data.go
+++ b/metropolis/node/core/localstorage/directory_data.go
@@ -67,9 +67,12 @@
 	}
 	d.mounted = true
 
-	key := make([]byte, keySize)
-	for i := uint16(0); i < keySize; i++ {
-		key[i] = config.NodeUnlockKey[i] ^ clusterUnlockKey[i]
+	var key []byte
+	if mode != crypt.ModeInsecure {
+		key = make([]byte, keySize)
+		for i := uint16(0); i < keySize; i++ {
+			key[i] = config.NodeUnlockKey[i] ^ clusterUnlockKey[i]
+		}
 	}
 
 	target, err := crypt.Map("data", crypt.NodeDataRawPath, key, mode)
diff --git a/metropolis/node/core/localstorage/storage_esp.go b/metropolis/node/core/localstorage/storage_esp.go
index 9da948a..c1779e9 100644
--- a/metropolis/node/core/localstorage/storage_esp.go
+++ b/metropolis/node/core/localstorage/storage_esp.go
@@ -181,7 +181,7 @@
 	return nil
 }
 
-func (e *ESPSealedConfiguration) Unseal() (*ppb.SealedConfiguration, error) {
+func (e *ESPSealedConfiguration) Unseal(tpmUsage cpb.NodeTPMUsage) (*ppb.SealedConfiguration, error) {
 	bytes, err := e.Read()
 	if err != nil {
 		if os.IsNotExist(err) {
@@ -190,27 +190,16 @@
 		return nil, fmt.Errorf("%w: when reading sealed data: %v", ErrSealedUnavailable, err)
 	}
 
-	bytes, err = tpm.Unseal(bytes)
-	if err != nil {
-		return nil, fmt.Errorf("%w: when unsealing: %v", ErrSealedCorrupted, err)
-	}
-
-	config := ppb.SealedConfiguration{}
-	err = proto.Unmarshal(bytes, &config)
-	if err != nil {
-		return nil, fmt.Errorf("%w: when unmarshaling: %v", ErrSealedCorrupted, err)
-	}
-
-	return &config, nil
-}
-
-func (e *ESPSealedConfiguration) ReadUnsafe() (*ppb.SealedConfiguration, error) {
-	bytes, err := e.Read()
-	if err != nil {
-		if os.IsNotExist(err) {
-			return nil, ErrNoSealed
+	switch tpmUsage {
+	case cpb.NodeTPMUsage_NODE_TPM_PRESENT_AND_USED:
+		bytes, err = tpm.Unseal(bytes)
+		if err != nil {
+			return nil, fmt.Errorf("%w: when unsealing: %v", ErrSealedCorrupted, err)
 		}
-		return nil, fmt.Errorf("%w: when reading sealed data: %v", ErrSealedUnavailable, err)
+	case cpb.NodeTPMUsage_NODE_TPM_PRESENT_BUT_UNUSED:
+	case cpb.NodeTPMUsage_NODE_TPM_NOT_PRESENT:
+	default:
+		return nil, fmt.Errorf("unknown tpmUsage %d", tpmUsage)
 	}
 
 	config := ppb.SealedConfiguration{}
diff --git a/metropolis/node/core/roleserve/worker_controlplane.go b/metropolis/node/core/roleserve/worker_controlplane.go
index a49343f..b6846a0 100644
--- a/metropolis/node/core/roleserve/worker_controlplane.go
+++ b/metropolis/node/core/roleserve/worker_controlplane.go
@@ -300,7 +300,7 @@
 				if err = creds.Save(&s.storageRoot.Data.Node.Credentials); err != nil {
 					return fmt.Errorf("while saving node credentials: %w", err)
 				}
-				sc, err := s.storageRoot.ESP.Metropolis.SealedConfiguration.Unseal()
+				sc, err := s.storageRoot.ESP.Metropolis.SealedConfiguration.Unseal(b.nodeTPMUsage)
 				if err != nil {
 					return fmt.Errorf("reading sealed configuration failed: %w", err)
 				}