summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2016-09-23 18:09:45 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-24 16:22:18 -0700
commit2446e3bfc089c7e65e41c90809ea70e9d051be91 (patch)
treee7e41e2b5f4949056ec5ce6eb6fe1690980d12b0
parent2e0c2177b53cfb67b3102ee51942e8ba7aea65e3 (diff)
downloadchrome-ec-2446e3bfc089c7e65e41c90809ea70e9d051be91.tar.gz
Cr50: Clear NVMEM before unlocking the console
The Cr50 console provides access to all sorts of dangerous commands. To protect user secrets, we must erase the persistent storage before unlocking the console. Note that this will not powerwash the AP, leaving you with the impression that you've just forgotten your password. You'll have to manually powerwash (Ctrl+Alt+Shift+R) afterwards. That will be addressed in a future CL. BUG=chrome-os-partner:55728 BRANCH=none TEST=make buildall, test on Gru Lock the console if it's not already ("lock enable"), then unlock it with "lock disable". Confirm that the NVMEM region is erased following a successful unlock process. Change-Id: Iebcd69c9f757f5ab5d496218f065197d3f1f746c Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/382666 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/cr50/board.c21
-rw-r--r--board/cr50/wp.c25
-rw-r--r--common/nvmem.c5
-rw-r--r--include/nvmem.h10
4 files changed, 50 insertions, 11 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index c967871c8e..1bb6ce46ec 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -450,6 +450,27 @@ int is_ec_rst_asserted(void)
return GREAD(RBOX, ASSERT_EC_RST);
}
+void nvmem_wipe_or_reboot(void)
+{
+ /*
+ * Blindly zapping the TPM space while the AP is awake and poking at it
+ * will bork the TPM task and the AP itself, so force the whole system
+ * off by holding the EC in reset.
+ */
+ assert_ec_rst();
+
+ /*
+ * If we can't clear the NVMEM or can't reset the TPM task, something
+ * is unexpectedly wrong. To be safe, let's reboot the Cr50 (which also
+ * reboots the EC and AP).
+ */
+ if (nvmem_setup(0) != EC_SUCCESS || tpm_reset() != 1)
+ system_reset(SYSTEM_RESET_HARD);
+
+ /* Wipe & reset is complete. Allow the EC and AP to reboot */
+ deassert_ec_rst();
+}
+
void nvmem_compute_sha(uint8_t *p_buf, int num_bytes,
uint8_t *p_sha, int sha_len)
{
diff --git a/board/cr50/wp.c b/board/cr50/wp.c
index 2800338555..8467370eb2 100644
--- a/board/cr50/wp.c
+++ b/board/cr50/wp.c
@@ -6,6 +6,7 @@
#include "common.h"
#include "console.h"
#include "hooks.h"
+#include "nvmem.h"
#include "registers.h"
#include "system.h"
#include "task.h"
@@ -62,22 +63,25 @@ static int unlock_in_progress;
/* Only invoked when the unlock sequence is done, either good or bad. */
static void unlock_sequence_is_over(void)
{
+ /* Disable the power button interrupt so we aren't bothered */
+ GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 0);
+ task_disable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT);
+
if (unlock_in_progress) {
+ /* We didn't poke the button fast enough */
CPRINTS("Unlock process failed");
} else {
+ /* The last poke was after the final deadline, so we're done */
CPRINTS("Unlock process completed successfully");
+ nvmem_wipe_or_reboot();
console_restricted_state = 0;
+ CPRINTS("TPM is erased, console is unlocked.");
}
unlock_in_progress = 0;
- /* Disable power button interrupt */
- GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 0);
- task_disable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT);
-
/* Allow sleeping again */
enable_sleep(SLEEP_MASK_FORCE_NO_DSLEEP);
-
}
DECLARE_DEFERRED(unlock_sequence_is_over);
@@ -91,7 +95,7 @@ static void power_button_poked(void)
} else {
/* Wait for the next poke */
hook_call_deferred(&unlock_sequence_is_over_data, UNLOCK_BEAT);
- CPRINTS("poke");
+ CPRINTS("poke: not yet %.6ld", unlock_deadline);
}
GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1);
@@ -131,6 +135,10 @@ static int start_the_unlock_process(void)
}
/****************************************************************************/
+static const char warning[] = "\n\t!!! WARNING !!!\n\n"
+ "\tThe AP will be impolitely shut down and the TPM persistent memory\n"
+ "\tERASED before the console is unlocked. If this is not what you\n"
+ "\twant, simply do nothing and the unlock process will fail.\n\n";
static int command_lock(int argc, char **argv)
{
@@ -164,9 +172,12 @@ static int command_lock(int argc, char **argv)
return EC_ERROR_BUSY;
}
+ /* Warn about the side effects of wiping nvmem */
+ ccputs(warning);
+
/* Now the user has to sit there and poke the button */
ccprintf("Start poking the power button in ");
- for (i = 5; i; i--) {
+ for (i = 10; i; i--) {
ccprintf("%d ", i);
sleep(1);
}
diff --git a/common/nvmem.c b/common/nvmem.c
index b3470b9889..3696d00279 100644
--- a/common/nvmem.c
+++ b/common/nvmem.c
@@ -314,14 +314,13 @@ int nvmem_setup(uint8_t starting_version)
* both corrupted
*/
for (part = 0; part < NVMEM_NUM_PARTITIONS; part++) {
- /* Set active partition variable */
- nvmem_act_partition = part;
/* Get the cache buffer */
if (nvmem_lock_cache() != EC_SUCCESS) {
CPRINTF("NvMem: Cache ram not available!\n");
return EC_ERROR_TIMEOUT;
}
-
+ /* Set active partition variable */
+ nvmem_act_partition = part;
/* Fill entire partition to 0xFFs */
memset(cache.base_ptr, 0xff, NVMEM_PARTITION_SIZE);
/* Get pointer to start of partition */
diff --git a/include/nvmem.h b/include/nvmem.h
index 781ea219f0..354e763c8d 100644
--- a/include/nvmem.h
+++ b/include/nvmem.h
@@ -51,9 +51,10 @@
* CONFIG_FLASH_NVMEM_BASE_(A|B) -> address of start of each partition
*
* The board.h file must define a macro or enum named NVMEM_NUM_USERS.
- * The board.c file must include 1 function and an array of user buffer lengths
+ * The board.c file must implement:
* nvmem_user_sizes[] -> array of user buffer lengths
* nvmem_compute_sha() -> function used to compute 4 byte sha (or equivalent)
+ * nvmem_wipe() -> function to erase and reformat the users' storage
*
* Note that total length of user buffers must satisfy the following:
* sum(user sizes) <= (NVMEM_PARTITION_SIZE) - sizeof(struct nvmem_tag)
@@ -176,4 +177,11 @@ int nvmem_setup(uint8_t version);
void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha,
int sha_len);
+/*
+ * Erase and reformat the entire nvmem storage space. This returns only if it
+ * was successful. If it fails, we can't be certain of the state of the system,
+ * so it should do a hard reboot to be safe.
+ */
+void nvmem_wipe_or_reboot(void);
+
#endif /* __CROS_EC_NVMEM_UTILS_H */