summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYicheng Li <yichengli@chromium.org>2019-05-22 13:47:14 -0700
committerCommit Bot <commit-bot@chromium.org>2019-06-07 22:45:22 +0000
commit8e7a7fb6cf9e7afcd1b80911c14ae76e8b9860fc (patch)
treed7b36abb4f7c6f9e4244f8c022b6f0119e070073
parent9985215ea27b059e83870d4f7f93918ae058c2dd (diff)
downloadchrome-ec-8e7a7fb6cf9e7afcd1b80911c14ae76e8b9860fc.tar.gz
fpsensor: Add API to check FP sensor encryption status.
Add EC command for the host to query FP sensor encryption status. Currently it's just FP TPM seed has been set or not. Add unit test for this command. Also add ectool command for querying encryption status. BRANCH=nocturne BUG=chromium:952275 TEST=ran unittests TEST=tested enrollment, matching and multifinger on DUT nocturne. TEST=tested querying sensor encryption status using ectool. Change-Id: I07d1e471ead85a517105b38d1ddd793c3046ce8f Signed-off-by: Yicheng Li <yichengli@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1633272 Reviewed-by: Nicolas Norvez <norvez@chromium.org>
-rw-r--r--common/fpsensor/build.mk7
-rw-r--r--common/fpsensor/fpsensor_state.c31
-rw-r--r--include/ec_commands.h12
-rw-r--r--include/fpsensor_state.h3
-rw-r--r--test/build.mk2
-rw-r--r--test/fpsensor.c105
-rw-r--r--test/fpsensor.tasklist11
-rw-r--r--util/ectool.c28
8 files changed, 191 insertions, 8 deletions
diff --git a/common/fpsensor/build.mk b/common/fpsensor/build.mk
index c70772635b..3b03152b05 100644
--- a/common/fpsensor/build.mk
+++ b/common/fpsensor/build.mk
@@ -7,6 +7,7 @@
# Note that this variable includes the trailing "/"
_fpsensor_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
-all-obj-$(HAS_TASK_FPSENSOR)+= \
- $(_fpsensor_dir)/fpsensor.o \
- $(_fpsensor_dir)/fpsensor_state.o
+all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)/fpsensor_state.o
+ifneq ($(CONFIG_SPI_FP_PORT),)
+all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)/fpsensor.o
+endif
diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c
index c9beeb1f82..f8016b49e9 100644
--- a/common/fpsensor/fpsensor_state.c
+++ b/common/fpsensor/fpsensor_state.c
@@ -36,13 +36,21 @@ uint32_t templ_dirty;
uint32_t user_id[FP_CONTEXT_USERID_WORDS];
/* Part of the IKM used to derive encryption keys received from the TPM. */
uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES];
-/* Flag indicating whether the seed has been initialised or not. */
-static int fp_tpm_seed_set;
+/* Status of the FP encryption engine. */
+static uint32_t fp_encryption_status;
uint32_t fp_events;
uint32_t sensor_mode;
+void fp_task_simulate(void)
+{
+ int timeout_us = -1;
+
+ while (1)
+ task_wait_event(timeout_us);
+}
+
void fp_clear_finger_context(int idx)
{
memset(fp_template[idx], 0, sizeof(fp_template[0]));
@@ -81,12 +89,12 @@ static int fp_command_tpm_seed(struct host_cmd_handler_args *args)
return EC_RES_INVALID_PARAM;
}
- if (fp_tpm_seed_set) {
+ if (fp_encryption_status & FP_ENC_STATUS_SEED_SET) {
CPRINTS("Seed has already been set.");
return EC_RES_ACCESS_DENIED;
}
memcpy(tpm_seed, params->seed, sizeof(tpm_seed));
- fp_tpm_seed_set = 1;
+ fp_encryption_status |= FP_ENC_STATUS_SEED_SET;
return EC_RES_SUCCESS;
}
@@ -94,8 +102,21 @@ DECLARE_HOST_COMMAND(EC_CMD_FP_SEED, fp_command_tpm_seed, EC_VER_MASK(0));
int fp_tpm_seed_is_set(void)
{
- return fp_tpm_seed_set;
+ return fp_encryption_status & FP_ENC_STATUS_SEED_SET;
+}
+
+static int fp_command_encryption_status(struct host_cmd_handler_args *args)
+{
+ struct ec_response_fp_encryption_status *r = args->response;
+
+ r->valid_flags = FP_ENC_STATUS_SEED_SET;
+ r->status = fp_encryption_status;
+ args->response_size = sizeof(*r);
+
+ return EC_RES_SUCCESS;
}
+DECLARE_HOST_COMMAND(EC_CMD_FP_ENC_STATUS, fp_command_encryption_status,
+ EC_VER_MASK(0));
static int validate_fp_mode(const uint32_t mode)
{
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 9f75e5f278..cb6c5b0b26 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -5653,6 +5653,18 @@ struct ec_params_fp_seed {
uint8_t seed[FP_CONTEXT_TPM_BYTES];
} __ec_align4;
+#define EC_CMD_FP_ENC_STATUS 0x0409
+
+/* FP TPM seed has been set or not */
+#define FP_ENC_STATUS_SEED_SET BIT(0)
+
+struct ec_response_fp_encryption_status {
+ /* Used bits in encryption engine status */
+ uint32_t valid_flags;
+ /* Encryption engine status */
+ uint32_t status;
+} __ec_align4;
+
/*****************************************************************************/
/* Touchpad MCU commands: range 0x0500-0x05FF */
diff --git a/include/fpsensor_state.h b/include/fpsensor_state.h
index 3033ec19b4..4ca792035f 100644
--- a/include/fpsensor_state.h
+++ b/include/fpsensor_state.h
@@ -67,6 +67,9 @@ extern uint32_t fp_events;
extern uint32_t sensor_mode;
+/* Simulation for unit tests. */
+void fp_task_simulate(void);
+
/*
* Clear one fingerprint template.
*
diff --git a/test/build.mk b/test/build.mk
index 93ae9d405a..f3fc169bc0 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -32,6 +32,7 @@ test-list-host += flash
test-list-host += flash_log
test-list-host += float
test-list-host += fp
+test-list-host += fpsensor
test-list-host += hooks
test-list-host += host_command
test-list-host += inductive_charging
@@ -98,6 +99,7 @@ extpwr_gpio-y=extpwr_gpio.o
fan-y=fan.o
flash-y=flash.o
flash_log-y=flash_log.o
+fpsensor-y=fpsensor.o
hooks-y=hooks.o
host_command-y=host_command.o
inductive_charging-y=inductive_charging.o
diff --git a/test/fpsensor.c b/test/fpsensor.c
new file mode 100644
index 0000000000..82e68ffe94
--- /dev/null
+++ b/test/fpsensor.c
@@ -0,0 +1,105 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "common.h"
+#include "ec_commands.h"
+#include "fpsensor_state.h"
+#include "host_command.h"
+#include "test_util.h"
+#include "util.h"
+
+static int check_fp_enc_status_valid_flags(const uint32_t expected)
+{
+ int rv;
+ struct ec_response_fp_encryption_status resp = { 0 };
+
+ rv = test_send_host_command(EC_CMD_FP_ENC_STATUS, 0,
+ NULL, 0,
+ &resp, sizeof(resp));
+ if (rv != EC_RES_SUCCESS) {
+ ccprintf("%s:%s(): failed to get encryption status. rv = %d\n",
+ __FILE__, __func__, rv);
+ return -1;
+ }
+
+ if (resp.valid_flags != expected) {
+ ccprintf("%s:%s(): expected valid flags 0x%08x, got 0x%08x\n",
+ __FILE__, __func__, expected, resp.valid_flags);
+ return -1;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+static int check_fp_tpm_seed_not_set(void)
+{
+ int rv;
+ struct ec_response_fp_encryption_status resp = { 0 };
+
+ /* Initially the seed should not have been set. */
+ rv = test_send_host_command(EC_CMD_FP_ENC_STATUS, 0,
+ NULL, 0,
+ &resp, sizeof(resp));
+ if (rv != EC_RES_SUCCESS || resp.status & FP_ENC_STATUS_SEED_SET) {
+ ccprintf("%s:%s(): rv = %d, seed is set: %d\n", __FILE__,
+ __func__, rv, resp.status & FP_ENC_STATUS_SEED_SET);
+ return -1;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+static int set_fp_tpm_seed(void)
+{
+ /*
+ * TODO(yichengli): test setting the seed twice:
+ * the second time fails;
+ * the seed is still set.
+ */
+ int rv;
+ struct ec_params_fp_seed params;
+ struct ec_response_fp_encryption_status resp = { 0 };
+
+ params.struct_version = FP_TEMPLATE_FORMAT_VERSION;
+ params.seed[0] = 0;
+
+ rv = test_send_host_command(EC_CMD_FP_SEED, 0,
+ &params, sizeof(params),
+ NULL, 0);
+ if (rv != EC_RES_SUCCESS) {
+ ccprintf("%s:%s(): rv = %d, set seed failed\n",
+ __FILE__, __func__, rv);
+ return -1;
+ }
+
+ /* Now seed should have been set. */
+ rv = test_send_host_command(EC_CMD_FP_ENC_STATUS, 0,
+ NULL, 0,
+ &resp, sizeof(resp));
+ if (rv != EC_RES_SUCCESS || !(resp.status & FP_ENC_STATUS_SEED_SET)) {
+ ccprintf("%s:%s(): rv = %d, seed is set: %d\n", __FILE__,
+ __func__, rv, resp.status & FP_ENC_STATUS_SEED_SET);
+ return -1;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+test_static int test_fpsensor(void)
+{
+ TEST_ASSERT(check_fp_enc_status_valid_flags(FP_ENC_STATUS_SEED_SET) ==
+ EC_RES_SUCCESS);
+ TEST_ASSERT(check_fp_tpm_seed_not_set() == EC_RES_SUCCESS);
+ TEST_ASSERT(set_fp_tpm_seed() == EC_RES_SUCCESS);
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ RUN_TEST(test_fpsensor);
+
+ test_print_result();
+}
diff --git a/test/fpsensor.tasklist b/test/fpsensor.tasklist
new file mode 100644
index 0000000000..bee999ff6b
--- /dev/null
+++ b/test/fpsensor.tasklist
@@ -0,0 +1,11 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST \
+ TASK_TEST(FPSENSOR, fp_task_simulate, NULL, TASK_STACK_SIZE)
+
diff --git a/util/ectool.c b/util/ectool.c
index f306e47cc5..76f3c2cc18 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -133,6 +133,8 @@ const char help_str[] =
" Reads from EC flash to a file\n"
" flashwrite <offset> <infile>\n"
" Writes to EC flash from a file\n"
+ " fpencstatus\n"
+ " Prints status of Fingerprint sensor encryption engine\n"
" fpframe\n"
" Retrieve the finger image as a PGM image\n"
" fpinfo\n"
@@ -1657,6 +1659,31 @@ int cmd_fp_info(int argc, char *argv[])
return 0;
}
+static void print_fp_enc_flags(const char *desc, uint32_t flags)
+{
+ printf("%s 0x%08x", desc, flags);
+ if (flags & FP_ENC_STATUS_SEED_SET)
+ printf(" FPTPM_seed_set");
+ printf("\n");
+}
+
+int cmd_fp_enc_status(int argc, char *argv[])
+{
+ int rv;
+ struct ec_response_fp_encryption_status resp = { 0 };
+
+ rv = ec_command(EC_CMD_FP_ENC_STATUS, 0, NULL, 0, &resp, sizeof(resp));
+ if (rv < 0) {
+ printf("Get FP sensor encryption status failed.\n");
+ } else {
+ print_fp_enc_flags("FPMCU encryption status:", resp.status);
+ print_fp_enc_flags("Valid flags: ",
+ resp.valid_flags);
+ rv = 0;
+ }
+ return rv;
+}
+
int cmd_fp_frame(int argc, char *argv[])
{
struct ec_response_fp_info r;
@@ -8660,6 +8687,7 @@ const struct command commands[] = {
{"flashspiinfo", cmd_flash_spi_info},
{"flashpd", cmd_flash_pd},
{"forcelidopen", cmd_force_lid_open},
+ {"fpencstatus", cmd_fp_enc_status},
{"fpframe", cmd_fp_frame},
{"fpinfo", cmd_fp_info},
{"fpmode", cmd_fp_mode},