summaryrefslogtreecommitdiff
path: root/common/fpsensor
diff options
context:
space:
mode:
authorYicheng Li <yichengli@chromium.org>2019-06-14 18:21:17 -0700
committerCommit Bot <commit-bot@chromium.org>2019-10-09 03:43:59 +0000
commit83e0848263313dbdaf10ebc887dea548faaf251a (patch)
tree9e5175d0fdee0265ef0d96fc6705fded4917c246 /common/fpsensor
parent635f21d41c095f138cb711118a7866fcd0b5bcc4 (diff)
downloadchrome-ec-83e0848263313dbdaf10ebc887dea548faaf251a.tar.gz
fpsensor: Implement command to read positive_match_secret.
Add EC command to read positive_match_secret on match success. If the attempt to read is 5 seconds after the match, the read is not allowed (the readable bit for positive match secret is cleared). Test that the command can read the data correctly and can read for each finger only once. Test that attempt to read secret after deadline will be rejected. BRANCH=nocturne BUG=chromium:927095 TEST=make buildall TEST=tested enrollment, matching and multifinger on DUT nocturne TEST=tested that if biod requests to download template and secret for a finger that's not currently matched, reading secret will fail. Change-Id: Idc734c6392d271e2aaee1cddf7c2c5b81b727b4a Signed-off-by: Yicheng Li <yichengli@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1679372 Reviewed-by: Nicolas Norvez <norvez@chromium.org>
Diffstat (limited to 'common/fpsensor')
-rw-r--r--common/fpsensor/fpsensor.c17
-rw-r--r--common/fpsensor/fpsensor_state.c78
2 files changed, 88 insertions, 7 deletions
diff --git a/common/fpsensor/fpsensor.c b/common/fpsensor/fpsensor.c
index 707ed1feab..5377b526b6 100644
--- a/common/fpsensor/fpsensor.c
+++ b/common/fpsensor/fpsensor.c
@@ -21,7 +21,6 @@
#include "system.h"
#include "task.h"
#include "trng.h"
-#include "timer.h"
#include "util.h"
#include "watchdog.h"
@@ -52,7 +51,6 @@ static uint32_t matching_time_us;
static uint32_t overall_time_us;
static timestamp_t overall_t0;
static uint8_t timestamps_invalid;
-static int8_t template_matched;
BUILD_ASSERT(sizeof(struct ec_fp_template_encryption_metadata) % 4 == 0);
@@ -130,20 +128,21 @@ static uint32_t fp_process_match(void)
timestamp_t t0 = get_time();
int res = -1;
uint32_t updated = 0;
- int32_t fgr = -1;
+ int32_t fgr = FP_NO_SUCH_TEMPLATE;
/* match finger against current templates */
- template_matched = -1;
+ fp_disable_positive_match_secret(&positive_match_secret_state);
CPRINTS("Matching/%d ...", templ_valid);
if (templ_valid) {
res = fp_finger_match(fp_template[0], templ_valid, fp_buffer,
&fgr, &updated);
CPRINTS("Match =>%d (finger %d)", res, fgr);
- if (res < 0) {
+ if (res < 0 || fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) {
res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL;
timestamps_invalid |= FPSTATS_MATCHING_INV;
} else {
- template_matched = (int8_t)fgr;
+ fp_enable_positive_match_secret(fgr,
+ &positive_match_secret_state);
}
if (res == EC_MKBP_FP_ERR_MATCH_YES_UPDATED)
templ_dirty |= updated;
@@ -458,7 +457,11 @@ static enum ec_status fp_command_stats(struct host_cmd_handler_args *args)
r->overall_t0.lo = overall_t0.le.lo;
r->overall_t0.hi = overall_t0.le.hi;
r->timestamps_invalid = timestamps_invalid;
- r->template_matched = template_matched;
+ /*
+ * Note that this is set to FP_NO_SUCH_TEMPLATE when positive match
+ * secret is read/disabled, and we are not using this field in biod.
+ */
+ r->template_matched = positive_match_secret_state.template_matched;
args->response_size = sizeof(*r);
return EC_RES_SUCCESS;
diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c
index 7618dbd859..82a548b8af 100644
--- a/common/fpsensor/fpsensor_state.c
+++ b/common/fpsensor/fpsensor_state.c
@@ -7,6 +7,7 @@
#include "cryptoc/util.h"
#include "ec_commands.h"
#include "fpsensor.h"
+#include "fpsensor_crypto.h"
#include "fpsensor_private.h"
#include "fpsensor_state.h"
#include "host_command.h"
@@ -30,6 +31,13 @@ uint8_t fp_enc_buffer[FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE]
/* Salt used in derivation of positive match secret. */
uint8_t fp_positive_match_salt
[FP_MAX_FINGER_COUNT][FP_POSITIVE_MATCH_SALT_BYTES];
+
+struct positive_match_secret_state positive_match_secret_state = {
+ .template_matched = FP_NO_SUCH_TEMPLATE,
+ .readable = false,
+ .deadline.val = 0,
+};
+
/* Number of used templates */
uint32_t templ_valid;
/* Bitmap of the templates with local modifications */
@@ -74,6 +82,7 @@ static void _fp_clear_context(void)
always_memset(fp_buffer, 0, sizeof(fp_buffer));
always_memset(fp_enc_buffer, 0, sizeof(fp_enc_buffer));
always_memset(user_id, 0, sizeof(user_id));
+ fp_disable_positive_match_secret(&positive_match_secret_state);
for (idx = 0; idx < FP_MAX_FINGER_COUNT; idx++)
fp_clear_finger_context(idx);
}
@@ -231,3 +240,72 @@ static enum ec_status fp_command_context(struct host_cmd_handler_args *args)
return EC_RES_INVALID_PARAM;
}
DECLARE_HOST_COMMAND(EC_CMD_FP_CONTEXT, fp_command_context, EC_VER_MASK(1));
+
+int fp_enable_positive_match_secret(uint32_t fgr,
+ struct positive_match_secret_state *state)
+{
+ timestamp_t now;
+
+ if (state->readable) {
+ CPRINTS("Error: positive match secret already readable.");
+ fp_disable_positive_match_secret(state);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ now = get_time();
+ state->template_matched = fgr;
+ state->readable = true;
+ state->deadline.val = now.val + (5 * SECOND);
+ return EC_SUCCESS;
+}
+
+void fp_disable_positive_match_secret(
+ struct positive_match_secret_state *state)
+{
+ state->template_matched = FP_NO_SUCH_TEMPLATE;
+ state->readable = false;
+ state->deadline.val = 0;
+}
+
+static enum ec_status fp_command_read_match_secret(
+ struct host_cmd_handler_args *args)
+{
+ const struct ec_params_fp_read_match_secret *params = args->params;
+ struct ec_response_fp_read_match_secret *response = args->response;
+ int8_t fgr = params->fgr;
+ timestamp_t now = get_time();
+ struct positive_match_secret_state state_copy
+ = positive_match_secret_state;
+
+ fp_disable_positive_match_secret(&positive_match_secret_state);
+
+ if (fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) {
+ CPRINTS("Invalid finger number %d", fgr);
+ return EC_RES_INVALID_PARAM;
+ }
+ if (timestamp_expired(state_copy.deadline, &now)) {
+ CPRINTS("Reading positive match secret disallowed: "
+ "deadline has passed.");
+ return EC_RES_TIMEOUT;
+ }
+ if (fgr != state_copy.template_matched || !state_copy.readable) {
+ CPRINTS("Positive match secret for finger %d is not meant to "
+ "be read now.", fgr);
+ return EC_RES_ACCESS_DENIED;
+ }
+
+ if (derive_positive_match_secret(response->positive_match_secret,
+ fp_positive_match_salt[fgr])
+ != EC_SUCCESS) {
+ CPRINTS("Failed to derive positive match secret for finger %d",
+ fgr);
+ /* Keep the template and encryption salt. */
+ return EC_RES_ERROR;
+ }
+ CPRINTS("Derived positive match secret for finger %d", fgr);
+ args->response_size = sizeof(*response);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_FP_READ_MATCH_SECRET, fp_command_read_match_secret,
+ EC_VER_MASK(0));