summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-07-10 15:39:12 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-12-08 02:14:27 +0000
commitf964335860f66ce188961824e46d7a3ed1e3abc6 (patch)
tree2be8dd9eed489e06ed2d2a7824a12d7f342d0268
parent5a1c7c47bbb53b18c0d0a1036b5c82d1005cee4a (diff)
downloadchrome-ec-f964335860f66ce188961824e46d7a3ed1e3abc6.tar.gz
rollback: Add host command to add entropy
To generate a new secret, we add entropy (generated from local HW TRNG) to the existing secret (sha256(old secret || entropy)). This essentially re-keys the EC. On STM32H7, erasing rollback flash block can take up to 4 seconds, which exceeds the timeout of a normal host command. Therefore, ADD_ENTROPY command is asynchronous (adding the entropy itself is performed in a deferred hook), and its status must be checked repeatedly by the host. In some cases, it is critical that the old key is not left in the backup rollback block(s). For this purpose, we add a special action ADD_ENTROPY_RESET_ASYNC that adds entropy multiple times, until all the rollback blocks have been overwritten. MANUAL MERGE: fix conflict after dropping https://chromium-review.googlesource.com/1139028 that would not build. BRANCH=none BUG=b:111190988 TEST=EC> rollbackinfo DUT> ./ectool --name=cros_fp reboot_ec RO && \ sleep 0.3 && ./ectool --name=cros_fp addentropy EC> rollbackinfo => See that that a single rollback block has been overridden TEST=Repeat with ./ectool --name=cros_fp addentropy reset => See that both rollback blocks have been overridden Change-Id: I3058b0a91591fab543ba6890f7356e671016edfa Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1132826 Reviewed-by: Nicolas Norvez <norvez@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/1363829 Reviewed-by: YH Lin <yueherngl@chromium.org> Commit-Queue: YH Lin <yueherngl@chromium.org> Tested-by: YH Lin <yueherngl@chromium.org>
-rw-r--r--include/ec_commands.h25
-rw-r--r--util/ectool.c41
2 files changed, 66 insertions, 0 deletions
diff --git a/include/ec_commands.h b/include/ec_commands.h
index e56ffad9c1..2411bbfbd3 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -4780,6 +4780,31 @@ struct __ec_align1 ec_params_set_cbi {
uint8_t data[]; /* For string and raw data */
};
+/*
+ * Add entropy to the device secret (stored in the rollback region).
+ *
+ * Depending on the chip, the operation may take a long time (e.g. to erase
+ * flash), so the commands are asynchronous.
+ */
+#define EC_CMD_ADD_ENTROPY 0x0122
+
+enum add_entropy_action {
+ /* Add entropy to the current secret. */
+ ADD_ENTROPY_ASYNC = 0,
+ /*
+ * Add entropy, and also make sure that the previous secret is erased.
+ * (this can be implemented by adding entropy multiple times until
+ * all rolback blocks have been overwritten).
+ */
+ ADD_ENTROPY_RESET_ASYNC = 1,
+ /* Read back result from the previous operation. */
+ ADD_ENTROPY_GET_RESULT = 2,
+};
+
+struct __ec_align1 ec_params_rollback_add_entropy {
+ uint8_t action;
+};
+
/*****************************************************************************/
/* The command range 0x200-0x2FF is reserved for Rotor. */
diff --git a/util/ectool.c b/util/ectool.c
index 19d5745b1f..1935bc270f 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -51,6 +51,8 @@ static struct option long_opts[] = {
const char help_str[] =
"Commands:\n"
+ " addentropy [reset]\n"
+ " Add entropy to device secret\n"
" autofanctrl <on>\n"
" Turn on automatic fan speed control.\n"
" backlight <enabled>\n"
@@ -368,6 +370,44 @@ static int read_mapped_string(uint8_t offset, char *buffer, int max_size)
return ret;
}
+int cmd_add_entropy(int argc, char *argv[])
+{
+ struct ec_params_rollback_add_entropy p;
+ int rv;
+ int tries = 100; /* Wait for 10 seconds at most */
+
+ if (argc >= 2 && !strcmp(argv[1], "reset"))
+ p.action = ADD_ENTROPY_RESET_ASYNC;
+ else
+ p.action = ADD_ENTROPY_ASYNC;
+
+ rv = ec_command(EC_CMD_ADD_ENTROPY, 0, &p, sizeof(p), NULL, 0);
+
+ if (rv != EC_RES_SUCCESS)
+ goto out;
+
+ while (tries--) {
+ usleep(100000);
+
+ p.action = ADD_ENTROPY_GET_RESULT;
+ rv = ec_command(EC_CMD_ADD_ENTROPY, 0, &p, sizeof(p), NULL, 0);
+
+ if (rv == EC_RES_SUCCESS) {
+ printf("Entropy added successfully\n");
+ return EC_RES_SUCCESS;
+ }
+
+ /* Abort if EC returns an error other than EC_RES_BUSY. */
+ if (rv <= -EECRESULT && rv != -EECRESULT-EC_RES_BUSY)
+ goto out;
+ }
+
+ rv = -EECRESULT-EC_RES_TIMEOUT;
+out:
+ fprintf(stderr, "Failed to add entropy: %d\n", rv);
+ return rv;
+}
+
int cmd_hello(int argc, char *argv[])
{
struct ec_params_hello p;
@@ -7990,6 +8030,7 @@ int cmd_cec(int argc, char *argv[])
/* NULL-terminated list of commands */
const struct command commands[] = {
+ {"addentropy", cmd_add_entropy},
{"autofanctrl", cmd_thermal_auto_fan_ctrl},
{"backlight", cmd_lcd_backlight},
{"battery", cmd_battery},