diff options
author | Yicheng Li <yichengli@chromium.org> | 2019-06-14 18:21:17 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-09 03:43:59 +0000 |
commit | 83e0848263313dbdaf10ebc887dea548faaf251a (patch) | |
tree | 9e5175d0fdee0265ef0d96fc6705fded4917c246 /test/fpsensor.c | |
parent | 635f21d41c095f138cb711118a7866fcd0b5bcc4 (diff) | |
download | chrome-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 'test/fpsensor.c')
-rw-r--r-- | test/fpsensor.c | 176 |
1 files changed, 175 insertions, 1 deletions
diff --git a/test/fpsensor.c b/test/fpsensor.c index b31aa3b259..962295afbf 100644 --- a/test/fpsensor.c +++ b/test/fpsensor.c @@ -8,6 +8,7 @@ #include "fpsensor_crypto.h" #include "fpsensor_state.h" #include "host_command.h" +#include "mock/timer_mock.h" #include "test_util.h" #include "util.h" @@ -38,7 +39,8 @@ static const uint8_t fake_user_id[] = { }; /* - * |expected_positive_match_secret| is obtained by running BoringSSL locally. + * |expected_positive_match_secret_for_empty_user_id| is obtained by running + * BoringSSL locally. * From https://boringssl.googlesource.com/boringssl * commit 365b7a0fcbf273b1fa704d151059e419abd6cfb8 * @@ -601,6 +603,172 @@ test_static int test_fp_set_sensor_mode(void) return EC_SUCCESS; } +test_static int test_enable_positive_match_secret(void) +{ + struct positive_match_secret_state dumb_state = { + .template_matched = FP_NO_SUCH_TEMPLATE, + .readable = false, + .deadline.val = 0, + }; + timestamp_t now = get_time(); + + TEST_ASSERT(fp_enable_positive_match_secret(0, &dumb_state) == + EC_SUCCESS); + TEST_ASSERT(dumb_state.template_matched == 0); + TEST_ASSERT(dumb_state.readable == true); + TEST_ASSERT(dumb_state.deadline.val == now.val + (5 * SECOND)); + + /* Trying to enable again before reading secret should fail. */ + TEST_ASSERT(fp_enable_positive_match_secret(0, &dumb_state) == + EC_ERROR_UNKNOWN); + TEST_ASSERT(dumb_state.template_matched == FP_NO_SUCH_TEMPLATE); + TEST_ASSERT(dumb_state.readable == false); + TEST_ASSERT(dumb_state.deadline.val == 0); + + return EC_SUCCESS; +} + +test_static int test_disable_positive_match_secret(void) +{ + struct positive_match_secret_state dumb_state; + + TEST_ASSERT(fp_enable_positive_match_secret(0, &dumb_state) == + EC_SUCCESS); + fp_disable_positive_match_secret(&dumb_state); + TEST_ASSERT(dumb_state.template_matched == FP_NO_SUCH_TEMPLATE); + TEST_ASSERT(dumb_state.readable == false); + TEST_ASSERT(dumb_state.deadline.val == 0); + + return EC_SUCCESS; +} + +test_static int test_command_read_match_secret(void) +{ + int rv; + struct ec_params_fp_read_match_secret params; + struct ec_response_fp_read_match_secret resp; + timestamp_t now = get_time(); + + /* Invalid finger index should be rejected. */ + params.fgr = FP_NO_SUCH_TEMPLATE; + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), NULL, 0); + TEST_ASSERT(rv == EC_RES_INVALID_PARAM); + params.fgr = FP_MAX_FINGER_COUNT; + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), NULL, 0); + TEST_ASSERT(rv == EC_RES_INVALID_PARAM); + + memset(&resp, 0, sizeof(resp)); + /* GIVEN that finger index is valid. */ + params.fgr = 0; + + /* GIVEN that positive match secret is enabled. */ + fp_enable_positive_match_secret(params.fgr, + &positive_match_secret_state); + + /* GIVEN that salt is non-trivial. */ + memcpy(fp_positive_match_salt[0], fake_positive_match_salt, + sizeof(fp_positive_match_salt[0])); + /* THEN reading positive match secret should succeed. */ + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), &resp, sizeof(resp)); + if (rv != EC_RES_SUCCESS) { + ccprintf("%s:%s(): rv = %d\n", __FILE__, __func__, rv); + return -1; + } + /* AND the readable bit should be cleared after the read. */ + TEST_ASSERT(positive_match_secret_state.readable == false); + + TEST_ASSERT_ARRAY_EQ( + resp.positive_match_secret, + expected_positive_match_secret_for_empty_user_id, + sizeof(expected_positive_match_secret_for_empty_user_id)); + + /* + * Now try reading secret again. + * EVEN IF the deadline has not passed. + */ + positive_match_secret_state.deadline.val = now.val + 1 * SECOND; + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), NULL, 0); + /* + * This time the command should fail because the + * fp_pos_match_secret_readable bit is cleared when the secret was read + * the first time. + */ + TEST_ASSERT(rv == EC_RES_ACCESS_DENIED); + + return EC_SUCCESS; +} + +test_static int test_command_read_match_secret_wrong_finger(void) +{ + int rv; + struct ec_params_fp_read_match_secret params; + + /* GIVEN that the finger is not the matched or enrolled finger. */ + params.fgr = 0; + /* + * GIVEN that positive match secret is enabled for a different + * finger. + */ + fp_enable_positive_match_secret(params.fgr + 1, + &positive_match_secret_state); + + /* Reading secret will fail. */ + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), NULL, 0); + TEST_ASSERT(rv == EC_RES_ACCESS_DENIED); + return EC_SUCCESS; +} + +test_static int test_command_read_match_secret_timeout(void) +{ + int rv; + struct ec_params_fp_read_match_secret params; + + params.fgr = 0; + /* GIVEN that the read is too late. */ + fp_enable_positive_match_secret(params.fgr, + &positive_match_secret_state); + set_time(positive_match_secret_state.deadline); + + /* EVEN IF encryption salt is non-trivial. */ + memcpy(fp_positive_match_salt[0], fake_positive_match_salt, + sizeof(fp_positive_match_salt[0])); + /* Reading secret will fail. */ + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), NULL, 0); + TEST_ASSERT(rv == EC_RES_TIMEOUT); + return EC_SUCCESS; +} + +test_static int test_command_read_match_secret_unreadable(void) +{ + int rv; + struct ec_params_fp_read_match_secret params; + + params.fgr = 0; + /* GIVEN that the readable bit is not set. */ + fp_enable_positive_match_secret(params.fgr, + &positive_match_secret_state); + positive_match_secret_state.readable = false; + + /* EVEN IF the finger is just matched. */ + TEST_ASSERT(positive_match_secret_state.template_matched + == params.fgr); + + /* EVEN IF encryption salt is non-trivial. */ + memcpy(fp_positive_match_salt[0], fake_positive_match_salt, + sizeof(fp_positive_match_salt[0])); + /* Reading secret will fail. */ + rv = test_send_host_command(EC_CMD_FP_READ_MATCH_SECRET, 0, ¶ms, + sizeof(params), NULL, 0); + TEST_ASSERT(rv == EC_RES_ACCESS_DENIED); + return EC_SUCCESS; +} + void run_test(void) { /* These are independent of global state. */ @@ -622,6 +790,12 @@ void run_test(void) RUN_TEST(test_derive_new_pos_match_secret); RUN_TEST(test_derive_positive_match_secret_fail_rollback_fail); RUN_TEST(test_derive_positive_match_secret_fail_salt_trivial); + RUN_TEST(test_enable_positive_match_secret); + RUN_TEST(test_disable_positive_match_secret); + RUN_TEST(test_command_read_match_secret); + RUN_TEST(test_command_read_match_secret_wrong_finger); + RUN_TEST(test_command_read_match_secret_timeout); + RUN_TEST(test_command_read_match_secret_unreadable); test_print_result(); } |