mount-encrypted: finalize if keyfile missing

If a system key is available (could read TPM NVRAM), but the "finalization
needed" file exists, it means that we are in the situation where either
cryptohome was interrupted, or the TPM was temporarily unavailable at an
earlier boot. In this case, it is up to mount-encrypted to perform the
finalization. Before, we were making the very bad assumption that the
keyfile was valid if a system key was found, meaning we would delete the
"finalization needed" file, leaving us with no way to find the encryption
key leading to an OOBE on the next boot.

BUG=chrome-os-partner:15960
TEST=daisy build, manual testing
BRANCH=None

Change-Id: Ifb6d74d8a38100e00d9a4597c25a71a6c33f806c
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/39883
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Elly Jones <ellyjones@chromium.org>
Reviewed-by: Will Drewry <wad@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
diff --git a/utility/mount-encrypted.c b/utility/mount-encrypted.c
index d453b6b..a97db0c 100644
--- a/utility/mount-encrypted.c
+++ b/utility/mount-encrypted.c
@@ -749,6 +749,7 @@
 	int sparsefd;
 	struct statvfs stateful_statbuf;
 	uint64_t blocks_min, blocks_max;
+	int valid_keyfile = 0;
 
 	/* Use the "system key" to decrypt the "encryption key" stored in
 	 * the stateful partition.
@@ -766,6 +767,7 @@
 		 * so migration is finished.
 		 */
 		migrate_allowed = 0;
+		valid_keyfile = 1;
 	} else {
 		uint8_t useless_key[DIGEST_LENGTH];
 		sha256((char *)kStaticKeyFinalizationNeeded, useless_key);
@@ -976,11 +978,16 @@
 			needs_finalization(encryption_key);
 	} else {
 		/* If we're not rebuilding and we have a sane system
-		 * key, then we must have finalized. Force any required
-		 * clean up.
+		 * key, then we must either need finalization (if we
+		 * failed to finalize in Cryptohome), or we have already
+		 * finalized, but maybe failed to clean up.
 		 */
-		if (has_system_key)
-			finalized();
+		if (has_system_key) {
+			if (!valid_keyfile)
+				finalize(system_key, encryption_key);
+			else
+				finalized();
+		}
 	}
 
 	free(lodev);