diff options
Diffstat (limited to 'common/u2f.c')
-rw-r--r-- | common/u2f.c | 37 |
1 files changed, 34 insertions, 3 deletions
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; |