From 53534ea1da670669eec5be9144ddc549b9fe6bc3 Mon Sep 17 00:00:00 2001 From: Andrey Pronin Date: Thu, 2 Jan 2020 13:23:46 -0800 Subject: cr50: add checks to U2F_ATTEST This CL adds checks to U2F_ATTEST and rejects signing of the passed data if one of the following conditions is not satisfied: - reserved byte is 0, - public key matches the key associated with the keyhandle. BUG=b:147097407 TEST=test_that firmware_Cr50U2fCommands Change-Id: I10005742042a182a894eed243e006fcf14f68e28 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1984891 Reviewed-by: Andrey Pronin Reviewed-by: Vadim Bendebury Tested-by: Andrey Pronin Commit-Queue: Andrey Pronin Auto-Submit: Andrey Pronin (cherry picked from commit aa9cdf2daf1aa2b30866c2d3aa260b47ed40808a) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2003403 --- common/u2f.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'common/u2f.c') diff --git a/common/u2f.c b/common/u2f.c index bc55496fb6..8cef638d3a 100644 --- a/common/u2f.c +++ b/common/u2f.c @@ -148,6 +148,27 @@ static enum vendor_cmd_rc u2f_generate(enum vendor_cmd_cc code, } DECLARE_VENDOR_COMMAND(VENDOR_CC_U2F_GENERATE, u2f_generate); +static int verify_kh_pubkey(const uint8_t *key_handle, + const U2F_EC_POINT *public_key, int *matches) { + int rc; + U2F_EC_POINT kh_pubkey; + p256_int od, opk_x, opk_y; + + rc = u2f_origin_user_keypair(key_handle, &od, &opk_x, &opk_y); + if (rc != EC_SUCCESS) + return rc; + + /* Reconstruct the public key. */ + p256_to_bin(&opk_x, kh_pubkey.x); + p256_to_bin(&opk_y, kh_pubkey.y); + kh_pubkey.pointFormat = U2F_POINT_UNCOMPRESSED; + + *matches = + safe_memcmp(&kh_pubkey, public_key, sizeof(U2F_EC_POINT)) == 0; + + return EC_SUCCESS; +} + static int verify_kh_owned(const uint8_t *user_secret, const uint8_t *app_id, const uint8_t *key_handle, int *owned) { @@ -302,16 +323,26 @@ static inline int u2f_attest_verify_reg_resp(const uint8_t *user_secret, const uint8_t *data) { struct G2F_REGISTER_MSG *msg = (void *) data; - int kh_owned; + int verified; if (data_size != sizeof(struct G2F_REGISTER_MSG)) return VENDOR_RC_NOT_ALLOWED; + if (msg->reserved != 0) + return VENDOR_RC_NOT_ALLOWED; + if (verify_kh_owned(user_secret, msg->app_id, msg->key_handle, - &kh_owned) != EC_SUCCESS) + &verified) != EC_SUCCESS) + return VENDOR_RC_INTERNAL_ERROR; + + if (!verified) + return VENDOR_RC_NOT_ALLOWED; + + if (verify_kh_pubkey(msg->key_handle, &msg->public_key, &verified) != + EC_SUCCESS) return VENDOR_RC_INTERNAL_ERROR; - if (!kh_owned) + if (!verified) return VENDOR_RC_NOT_ALLOWED; return VENDOR_RC_SUCCESS; -- cgit v1.2.1