@@ -374,7 +374,9 @@ fail:
return rc;
}
-static int secboot_tpm_load_variable_bank(struct list_head *bank)
+
+/* Helper to validate the current active SECBOOT bank's data against the hash stored in the TPM */
+static int compare_bank_hash(void)
{
char bank_hash[SHA256_DIGEST_LENGTH];
uint64_t bit = tpmnv_control_image->active_bit;
@@ -394,6 +396,15 @@ static int secboot_tpm_load_variable_bank(struct list_head *bank)
/* Tampered pnor space detected, abandon ship */
return OPAL_PERMISSION;
+ return OPAL_SUCCESS;
+}
+
+
+static int secboot_tpm_load_variable_bank(struct list_head *bank)
+{
+ uint64_t bit = tpmnv_control_image->active_bit;
+ int rc;
+
rc = secboot_tpm_deserialize_from_buffer(bank, tpmnv_vars_image->vars, tpmnv_vars_size, SECVAR_FLAG_PROTECTED);
if (rc)
return rc;
@@ -692,8 +703,25 @@ static int secboot_tpm_store_init(void)
rc = secboot_format();
if (rc)
goto error;
+ goto done;
}
+ /* Verify the active bank's integrity by comparing against the hash in TPM.
+ * Reformat if it does not match -- we do not want to load potentially
+ * compromised data.
+ * Ideally, the backend driver should retain secure boot state in
+ * protected (TPM) storage, so secure boot state should be the same, albeit
+ * without the data in unprotected (PNOR) storage.
+ */
+ rc = compare_bank_hash();
+ if (rc == OPAL_PERMISSION) {
+ rc = secboot_format();
+ if (rc)
+ goto error;
+ }
+ else if (rc)
+ goto error;
+
done:
return OPAL_SUCCESS;
@@ -99,21 +99,6 @@ int run_test(void)
ASSERT(*((uint64_t*) secboot_image->bank[0]) != 0llu);
ASSERT(*((uint64_t*) secboot_image->bank[1]) != 0llu);
- clear_bank_list(&variable_bank);
-
- // Tamper with pnor, hash check should catch this
- secboot_image->bank[0][0] = ~secboot_image->bank[0][0];
-
- rc = secboot_tpm_load_bank(&variable_bank, SECVAR_VARIABLE_BANK);
- ASSERT(rc != OPAL_SUCCESS); // TODO: permission?
-
- // Fix it back...
- secboot_image->bank[0][0] = ~secboot_image->bank[0][0];
-
- // Should be ok again
- rc = secboot_tpm_load_bank(&variable_bank, SECVAR_VARIABLE_BANK);
- ASSERT(rc == OPAL_SUCCESS);
-
clear_bank_list(&variable_bank);
free(secboot_buffer);