summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hughes <tomhughes@chromium.org>2019-07-24 12:58:02 -0700
committerCommit Bot <commit-bot@chromium.org>2019-08-06 01:00:15 +0000
commit2cfd12facff02ead45addb10c4dd363402eb8898 (patch)
tree6ded7048c91d9646232136787f8e760a725a31b6
parent4e41a88f9e475631652986a116f07e85d848bf3b (diff)
downloadchrome-ec-2cfd12facff02ead45addb10c4dd363402eb8898.tar.gz
ectool/trng: Add "rand" host command for testing RNG
This host command and corresponding ectool command allows us to generate random numbers with the MCU's RNG and process the resulting output with tools to validate the statistical randomness, such as dieharder (https://webhome.phy.duke.edu/~rgb/General/dieharder.php) and NIST SP 800-22 (https://csrc.nist.gov/publications/detail/sp/800-22/rev-1a/final). BRANCH=none BUG=b:124770147 TEST=ectool --name=cros_fp rand 1 > rand.bin; ls -la rand.bin TEST=ectool --name=cros_fp rand 536 > rand.bin; ls -la rand.bin TEST=ectool --name=cros_fp rand 537 > rand.bin; ls -la rand.bin TEST=ectool --name=cros_fp rand 99999999999999999999999999 Change-Id: Ic0bda4deae79fc7465671dcacfe8bbc9a066b5e5 Signed-off-by: Tom Hughes <tomhughes@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1726822 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--chip/stm32/trng.c36
-rw-r--r--include/ec_commands.h19
-rw-r--r--util/ectool.c50
3 files changed, 103 insertions, 2 deletions
diff --git a/chip/stm32/trng.c b/chip/stm32/trng.c
index 94cfab995e..a5087df666 100644
--- a/chip/stm32/trng.c
+++ b/chip/stm32/trng.c
@@ -7,8 +7,10 @@
#include "common.h"
#include "console.h"
+#include "host_command.h"
#include "panic.h"
#include "registers.h"
+#include "system.h"
#include "task.h"
#include "trng.h"
#include "util.h"
@@ -95,7 +97,12 @@ test_mockable void exit_trng(void)
#endif
}
-#ifdef CONFIG_CMD_RAND
+#if defined(CONFIG_CMD_RAND)
+/*
+ * We want to avoid accidentally exposing debug commands in RO since we can't
+ * update RO once in production.
+ */
+#if defined(SECTION_IS_RW)
static int command_rand(int argc, char **argv)
{
uint8_t data[32];
@@ -110,4 +117,29 @@ static int command_rand(int argc, char **argv)
}
DECLARE_CONSOLE_COMMAND(rand, command_rand,
NULL, "Output random bytes to console.");
-#endif
+
+static int host_command_rand(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_rand_num *p = args->params;
+ struct ec_response_rand_num *r = args->response;
+ uint16_t num_rand_bytes = p->num_rand_bytes;
+
+ if (system_is_locked())
+ return EC_RES_ACCESS_DENIED;
+
+ if (num_rand_bytes > args->response_max)
+ return EC_RES_OVERFLOW;
+
+ init_trng();
+ rand_bytes(r->rand, num_rand_bytes);
+ exit_trng();
+
+ args->response_size = num_rand_bytes;
+
+ return EC_SUCCESS;
+}
+
+DECLARE_HOST_COMMAND(EC_CMD_RAND_NUM, host_command_rand,
+ EC_VER_MASK(EC_VER_RAND_NUM));
+#endif /* SECTION_IS_RW */
+#endif /* CONFIG_CMD_RAND */
diff --git a/include/ec_commands.h b/include/ec_commands.h
index b3f5878030..218fb04a00 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1750,6 +1750,25 @@ struct ec_params_flash_select {
} __ec_align4;
+/**
+ * Request random numbers to be generated and returned.
+ * Can be used to test the random number generator is truly random.
+ * See https://csrc.nist.gov/publications/detail/sp/800-22/rev-1a/final and
+ * https://webhome.phy.duke.edu/~rgb/General/dieharder.php.
+ */
+#define EC_CMD_RAND_NUM 0x001A
+#define EC_VER_RAND_NUM 0
+
+struct ec_params_rand_num {
+ uint16_t num_rand_bytes; /**< num random bytes to generate */
+} __ec_align4;
+
+struct ec_response_rand_num {
+ uint8_t rand[0]; /**< generated random numbers */
+} __ec_align4;
+
+BUILD_ASSERT(sizeof(struct ec_response_rand_num) == 0);
+
/*****************************************************************************/
/* PWM commands */
diff --git a/util/ectool.c b/util/ectool.c
index b77215bdb8..59feee5f39 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -242,6 +242,8 @@ const char help_str[] =
" Set keyboard backlight in percent\n"
" pwmsetduty\n"
" Set 16 bit duty cycle of given PWM\n"
+ " rand <num_bytes>\n"
+ " generate <num_bytes> of random numbers\n"
" readtest <patternoffset> <size>\n"
" Reads a pattern from the EC via LPC\n"
" reboot_ec <RO|RW|cold|hibernate|hibernate-clear-ap-off|disable-jump>"
@@ -1112,6 +1114,53 @@ int cmd_flash_info(int argc, char *argv[])
return 0;
}
+int cmd_rand(int argc, char *argv[])
+{
+ struct ec_params_rand_num p;
+ struct ec_response_rand_num *r;
+ size_t r_size;
+ int64_t num_bytes;
+ int64_t i;
+ char *e;
+ int rv = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <num_bytes>\n", argv[0]);
+ return -1;
+ }
+
+ num_bytes = strtol(argv[1], &e, 0);
+ if ((e && *e) || (errno == ERANGE)) {
+ fprintf(stderr, "Invalid num_bytes argument\n");
+ return -1;
+ }
+
+ r = ec_inbuf;
+
+ for (i = 0; i < num_bytes; i += ec_max_insize) {
+ p.num_rand_bytes = ec_max_insize;
+ if (num_bytes - i < p.num_rand_bytes)
+ p.num_rand_bytes = num_bytes - i;
+
+ r_size = p.num_rand_bytes;
+
+ rv = ec_command(EC_CMD_RAND_NUM, EC_VER_RAND_NUM, &p, sizeof(p),
+ r, r_size);
+ if (rv < 0) {
+ fprintf(stderr, "Random number command failed\n");
+ return -1;
+ }
+
+ rv = write(STDOUT_FILENO, r->rand, r_size);
+ if (rv != r_size) {
+ fprintf(stderr, "Failed to write stdout\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int cmd_flash_spi_info(int argc, char *argv[])
{
struct ec_response_flash_spi_info r;
@@ -9000,6 +9049,7 @@ const struct command commands[] = {
{"pwmsetfanrpm", cmd_pwm_set_fan_rpm},
{"pwmsetkblight", cmd_pwm_set_keyboard_backlight},
{"pwmsetduty", cmd_pwm_set_duty},
+ {"rand", cmd_rand},
{"readtest", cmd_read_test},
{"reboot_ec", cmd_reboot_ec},
{"rollbackinfo", cmd_rollback_info},