From 31bf4f49ecbbeb2ce4f4d86c334d4c3fa4144a26 Mon Sep 17 00:00:00 2001 From: Vadim Sukhomlinov Date: Wed, 13 Oct 2021 10:25:00 -0700 Subject: cr50: update U2F_Sign command to hash authentication secret U2F_Sign is expected to receive pre-hashed version of user credentials so should apply SHA2-256 to the value before key handle verification. Also, enforce user verification with authentication time secret if no user presence (power button press) is requested. test/tpm_test/tpmtest.py updated to apply SHA256 in U2F_Generate to match expected u2fd behavior. BUG=b:172971998 TEST=make BOARD=cr50 CRYPTO_TEST=1 U2F_TEST=1; test/tpm_test/tpmtest.py Signed-off-by: Vadim Sukhomlinov Change-Id: I92d73cd1fc0d962fefe11faeb4ce0ed68c798aa7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3221264 Reviewed-by: Vadim Sukhomlinov Reviewed-by: Andrey Pronin Reviewed-by: Howard Yang Tested-by: Vadim Sukhomlinov Commit-Queue: Vadim Sukhomlinov --- common/u2f.c | 23 ++++++++++++++++------- test/tpm_test/u2f_test.py | 3 +++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/common/u2f.c b/common/u2f.c index 4738bf0572..d164c49b2f 100644 --- a/common/u2f.c +++ b/common/u2f.c @@ -154,8 +154,8 @@ enum vendor_cmd_rc u2f_sign_cmd(enum vendor_cmd_cc code, void *buf, const struct u2f_state *state = u2f_get_state(); - const uint8_t *hash, *user, *origin, *authTimeSecret = NULL; - + const uint8_t *hash, *user, *origin; + uint8_t *authTimeSecret = NULL; uint8_t flags; struct u2f_sign_resp *resp; @@ -190,11 +190,10 @@ enum vendor_cmd_rc u2f_sign_cmd(enum vendor_cmd_cc code, void *buf, origin = req->v1.appId; /** * TODO(b/184393647): Enforce user verification if no user - * presence check is requested. Set - * authTimeSecret = req->v1.authTimeSecret; - * unconditionally or if (flags & U2F_AUTH_FLAG_TUP) == 0 + * presence check is requested. */ - authTimeSecret = NULL; + if ((flags & U2F_AUTH_FLAG_TUP) == 0) + authTimeSecret = (uint8_t *)req->v1.authTimeSecret; } else if (input_size == sizeof(struct u2f_sign_versioned_req_v2)) { kh = (union u2f_key_handle_variant *)&req->v2.keyHandle; kh_version = U2F_KH_VERSION_2; @@ -202,10 +201,20 @@ enum vendor_cmd_rc u2f_sign_cmd(enum vendor_cmd_cc code, void *buf, flags = req->v2.flags; user = req->v2.userSecret; origin = req->v2.appId; - authTimeSecret = req->v2.authTimeSecret; + authTimeSecret = (uint8_t *)req->v2.authTimeSecret; } else return VENDOR_RC_BOGUS_ARGS; + if (authTimeSecret) { + /** + * U2F_Sign receives a pre-hashed version of credential which + * was used by U2F_Generate, so perform hash before use. + */ + if (!DCRYPTO_SHA256_hash(authTimeSecret, + U2F_AUTH_TIME_SECRET_SIZE, + authTimeSecret)) + return VENDOR_RC_INTERNAL_ERROR; + } result = u2f_authorize_keyhandle(state, kh, kh_version, user, origin, authTimeSecret); if (result == EC_ERROR_ACCESS_DENIED) diff --git a/test/tpm_test/u2f_test.py b/test/tpm_test/u2f_test.py index 156399d740..8bbacd4eb3 100644 --- a/test/tpm_test/u2f_test.py +++ b/test/tpm_test/u2f_test.py @@ -19,6 +19,9 @@ def u2f_generate(tpm, origin, user, flag, auth): origin = origin[:32].ljust(32, b'\0') user = user[:32].ljust(32, b'\0') auth = auth[:32].ljust(32, b'\0') + + # U2F_Sign receives prehashed credentials, U2F_Generate - hashed + auth = hashlib.sha256(auth).digest() cmd = origin + user + flag.to_bytes(1, 'big') + auth wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.U2F_GENERATE, cmd)) response = tpm.unwrap_ext_response(subcmd.U2F_GENERATE, wrapped_response) -- cgit v1.2.1