summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Schilder <mschilder@google.com>2019-06-25 13:48:42 -0700
committerCommit Bot <commit-bot@chromium.org>2019-07-29 23:43:53 +0000
commit7c9aff6ff731db0da18f8fe8232196cf71fd09f4 (patch)
tree7707f6e58c73a62b316d34e94f523bae2579a32f
parent234c5298c8369e18eac135b50fc3dec61afe510e (diff)
downloadchrome-ec-7c9aff6ff731db0da18f8fe8232196cf71fd09f4.tar.gz
g: reset and wipe dcrypto engine after timeout.
In case of a timeout, we need to clean up state and make sure engine is ready for a subsequent call. Added dcrypto_test console command to test the various scenarios: stack overflow, infinite loop and cfi failure recovery. Signed-off-by: mschilder@google.com BUG=b:135772657 BRANCH=none TEST=run console command dcrypto_test; build and run cr53 Change-Id: I531a59de6f2cf6941c797aeeeabb10eb10f02c9b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1677229 Reviewed-by: Marius Schilder <mschilder@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Marius Schilder <mschilder@chromium.org> Commit-Queue: Marius Schilder <mschilder@chromium.org>
-rw-r--r--chip/g/dcrypto/dcrypto_runtime.c225
1 files changed, 203 insertions, 22 deletions
diff --git a/chip/g/dcrypto/dcrypto_runtime.c b/chip/g/dcrypto/dcrypto_runtime.c
index 052547a436..3f2efb54be 100644
--- a/chip/g/dcrypto/dcrypto_runtime.c
+++ b/chip/g/dcrypto/dcrypto_runtime.c
@@ -12,13 +12,44 @@
static struct mutex dcrypto_mutex;
static volatile task_id_t my_task_id;
-static int dcrypto_is_initialized;
+static uint8_t dcrypto_is_initialized;
-void dcrypto_init_and_lock(void)
+static const uint32_t wiped_value = 0xdddddddd;
+
+static void dcrypto_reset_and_wipe(void)
{
int i;
volatile uint32_t *ptr;
+ /* Reset. */
+ GREG32(CRYPTO, CONTROL) = GC_CRYPTO_CONTROL_RESET_MASK;
+ GREG32(CRYPTO, CONTROL) = 0;
+
+ /* Reset all the status bits. */
+ GREG32(CRYPTO, INT_STATE) = -1;
+
+ /* Wipe state. */
+ GREG32(CRYPTO, WIPE_SECRETS) = 1;
+
+ /* Wipe DMEM. */
+ ptr = GREG32_ADDR(CRYPTO, DMEM_DUMMY);
+ for (i = 0; i < DMEM_NUM_WORDS; ++i)
+ *ptr++ = wiped_value;
+}
+
+static void dcrypto_wipe_imem(void)
+{
+ int i;
+ volatile uint32_t *ptr;
+
+ /* Wipe IMEM. */
+ ptr = GREG32_ADDR(CRYPTO, IMEM_DUMMY);
+ for (i = 0; i < IMEM_NUM_WORDS; ++i)
+ *ptr++ = wiped_value;
+}
+
+void dcrypto_init_and_lock(void)
+{
mutex_lock(&dcrypto_mutex);
my_task_id = task_get_current();
@@ -29,9 +60,8 @@ void dcrypto_init_and_lock(void)
REG_WRITE_MLV(GR_PMU_PERICLKSET0, GC_PMU_PERICLKSET0_DCRYPTO0_CLK_MASK,
GC_PMU_PERICLKSET0_DCRYPTO0_CLK_LSB, 1);
- /* Reset. */
- REG_WRITE_MLV(GR_PMU_RST0, GC_PMU_RST0_DCRYPTO0_MASK,
- GC_PMU_RST0_DCRYPTO0_LSB, 0);
+ dcrypto_reset_and_wipe();
+ dcrypto_wipe_imem();
/* Turn off random nops (which are enabled by default). */
GWRITE_FIELD(CRYPTO, RAND_STALL_CTL, STALL_EN, 0);
@@ -40,25 +70,11 @@ void dcrypto_init_and_lock(void)
/* Now turn on random nops. */
GWRITE_FIELD(CRYPTO, RAND_STALL_CTL, STALL_EN, 1);
- /* Initialize DMEM. */
- ptr = GREG32_ADDR(CRYPTO, DMEM_DUMMY);
- for (i = 0; i < DMEM_NUM_WORDS; ++i)
- *ptr++ = 0xdddddddd;
-
- /* Initialize IMEM. */
- ptr = GREG32_ADDR(CRYPTO, IMEM_DUMMY);
- for (i = 0; i < IMEM_NUM_WORDS; ++i)
- *ptr++ = 0xdddddddd;
-
GREG32(CRYPTO, INT_STATE) = -1; /* Reset all the status bits. */
GREG32(CRYPTO, INT_ENABLE) = -1; /* Enable all status bits. */
task_enable_irq(GC_IRQNUM_CRYPTO0_HOST_CMD_DONE_INT);
- /* Reset. */
- GREG32(CRYPTO, CONTROL) = 1;
- GREG32(CRYPTO, CONTROL) = 0;
-
dcrypto_is_initialized = 1;
}
@@ -72,7 +88,7 @@ void dcrypto_unlock(void)
#endif
/*
* When running on Cr50 this event belongs in the TPM task event space. Make
- * sure there is no collision with events defined in ./common/tpm_regsters.c.
+ * sure there is no collision with events defined in ./common/tpm_registers.c.
*/
#define TASK_EVENT_DCRYPTO_DONE TASK_EVENT_CUSTOM_BIT(0)
@@ -92,8 +108,19 @@ uint32_t dcrypto_call(uint32_t adr)
/* TODO(ngm): switch return value to an enum. */
switch (event) {
case TASK_EVENT_DCRYPTO_DONE:
- return 0;
+ /*
+ * We expect only the CMD_RECV status bit to be set at this
+ * point. CMD_DONE got cleared in the interrupt handler. Any and
+ * all other bits are indicative of error.
+ * Except for MOD_OPERAND_OUT_OF_RANGE, which is noise.
+ */
+ if ((GREG32(CRYPTO, INT_STATE) &
+ ~(GC_CRYPTO_INT_STATE_MOD_OPERAND_OUT_OF_RANGE_MASK |
+ GC_CRYPTO_INT_STATE_HOST_CMD_RECV_MASK)) == 0)
+ return 0;
+ /* fall through */
default:
+ dcrypto_reset_and_wipe();
return 1;
}
}
@@ -101,7 +128,6 @@ uint32_t dcrypto_call(uint32_t adr)
void __keep dcrypto_done_interrupt(void)
{
GREG32(CRYPTO, INT_STATE) = GC_CRYPTO_INT_STATE_HOST_CMD_DONE_MASK;
- task_clear_pending_irq(GC_IRQNUM_CRYPTO0_HOST_CMD_DONE_INT);
task_set_event(my_task_id, TASK_EVENT_DCRYPTO_DONE, 0);
}
DECLARE_IRQ(GC_IRQNUM_CRYPTO0_HOST_CMD_DONE_INT, dcrypto_done_interrupt, 1);
@@ -142,3 +168,158 @@ uint32_t dcrypto_dmem_load(size_t offset, const void *words, size_t n_words)
}
return diff;
}
+
+#ifdef DCRYPTO_RUNTIME_TEST
+/*
+ * Add console command "dcrypto_test" that runs a couple of engine failure
+ * scenarios and checks for adequate handling thereof:
+ * - error return code
+ * - dmem erasure on error
+ * - dmem preservation on success
+ */
+#include "console.h"
+
+/* AUTO-GENERATED. DO NOT MODIFY. */
+/* clang-format off */
+static const uint32_t IMEM_test_hang[] = {
+/* @0x0: function forever[2] { */
+#define CF_forever_adr 0
+/*forever: */
+ 0x10080000, /* b forever */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x2: function func17[2] { */
+#define CF_func17_adr 2
+ 0x08000000, /* call &forever */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x4: function func16[2] { */
+#define CF_func16_adr 4
+ 0x08000002, /* call &func17 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x6: function func15[2] { */
+#define CF_func15_adr 6
+ 0x08000004, /* call &func16 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x8: function func14[2] { */
+#define CF_func14_adr 8
+ 0x08000006, /* call &func15 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0xa: function func13[2] { */
+#define CF_func13_adr 10
+ 0x08000008, /* call &func14 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0xc: function func12[2] { */
+#define CF_func12_adr 12
+ 0x0800000a, /* call &func13 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0xe: function func11[2] { */
+#define CF_func11_adr 14
+ 0x0800000c, /* call &func12 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x10: function func10[2] { */
+#define CF_func10_adr 16
+ 0x0800000e, /* call &func11 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x12: function func9[2] { */
+#define CF_func9_adr 18
+ 0x08000010, /* call &func10 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x14: function func8[2] { */
+#define CF_func8_adr 20
+ 0x08000012, /* call &func9 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x16: function func7[2] { */
+#define CF_func7_adr 22
+ 0x08000014, /* call &func8 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x18: function func6[2] { */
+#define CF_func6_adr 24
+ 0x08000016, /* call &func7 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x1a: function func5[2] { */
+#define CF_func5_adr 26
+ 0x08000018, /* call &func6 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x1c: function func4[2] { */
+#define CF_func4_adr 28
+ 0x0800001a, /* call &func5 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x1e: function func3[2] { */
+#define CF_func3_adr 30
+ 0x0800001c, /* call &func4 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x20: function func2[2] { */
+#define CF_func2_adr 32
+ 0x0800001e, /* call &func3 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x22: function func1[2] { */
+#define CF_func1_adr 34
+ 0x08000020, /* call &func2 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x24: function test[2] { */
+#define CF_test_adr 36
+ 0x08000022, /* call &func1 */
+ 0x0c000000, /* ret */
+/* } */
+/* @0x26: function sigchk[2] { */
+#define CF_sigchk_adr 38
+ 0xf8000004, /* sigini #4 */
+ 0xf9ccc3c2, /* sigchk #13419458 */
+/* } */
+};
+/* clang-format on */
+
+static int command_dcrypto_test(int argc, char *argv[])
+{
+ volatile uint32_t *ptr = GREG32_ADDR(CRYPTO, DMEM_DUMMY);
+ uint32_t not_wiped = ~wiped_value;
+ int result;
+
+ dcrypto_init_and_lock();
+ dcrypto_imem_load(0, IMEM_test_hang, ARRAY_SIZE(IMEM_test_hang));
+
+ *ptr = not_wiped;
+ result = dcrypto_call(CF_func2_adr); /* max legal stack, into hang */
+ if (result != 1 || *ptr != wiped_value)
+ ccprintf("dcrypto_test: fail1 %d,%08x\n", result, *ptr);
+
+ *ptr = not_wiped;
+ result = dcrypto_call(CF_test_adr); /* stack overflow */
+ if (result != 1 || *ptr != wiped_value)
+ ccprintf("dcrypto_test: fail2 %d,%08x\n", result, *ptr);
+
+ *ptr = not_wiped;
+ result = dcrypto_call(CF_sigchk_adr); /* cfi trap */
+ if (result != 1 || *ptr != wiped_value)
+ ccprintf("dcrypto_test: fail3 %d,%08x\n", result, *ptr);
+
+ *ptr = not_wiped;
+ result = dcrypto_call(CF_test_adr + 1); /* simple ret should succeed */
+ if (result != 0 || *ptr != not_wiped)
+ ccprintf("dcrypto_test: fail4 %d,%08x\n", result, *ptr);
+
+ dcrypto_unlock();
+
+ return EC_SUCCESS;
+}
+DECLARE_SAFE_CONSOLE_COMMAND(dcrypto_test, command_dcrypto_test, "",
+ "dcrypto test");
+
+#endif /* DCRYPTO_RUNTIME_TEST */