From 4743fd2326f365c1194ed74becbf386ae62cdf3d Mon Sep 17 00:00:00 2001 From: shimun Date: Tue, 9 Jun 2020 20:12:55 +0200 Subject: [PATCH] make led colour depend on credential --- fido2/ctap.c | 45 ++++++++++++++++++++++++++++------ fido2/device.h | 18 ++++++++++++++ targets/stm32l432/src/device.c | 9 ++++--- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/fido2/ctap.c b/fido2/ctap.c index 3ccb9cb..c77387e 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -461,7 +461,10 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf // Generate credRandom crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY2, 0, credRandom); crypto_sha256_update((uint8_t*)&ext->hmac_secret.credential->id, sizeof(CredentialId)); - crypto_sha256_update(&getAssertionState.user_verified, 1); + // using user_verified as len means it won't be included when false + if (getAssertionState.user_verified == 1) { + crypto_sha256_update(&getAssertionState.user_verified, 1); + } crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY2, 0, credRandom); // Decrypt saltEnc @@ -566,10 +569,10 @@ static unsigned int get_credential_id_size(int type) return sizeof(CredentialId); } -static int ctap2_user_presence_test() +static int ctap2_user_presence_test(uint32_t colour) { device_set_status(CTAPHID_STATUS_UPNEEDED); - int ret = ctap_user_presence_test(CTAP2_UP_DELAY_MS); + int ret = ctap_user_presence_test_colour(CTAP2_UP_DELAY_MS, colour); if ( ret > 1 ) { return CTAP2_ERR_PROCESSING; @@ -587,6 +590,30 @@ static int ctap2_user_presence_test() return CTAP2_ERR_ACTION_TIMEOUT; } } +static uint32_t ctap_assertion_led_colour(uint8_t * seed, uint32_t slen) +{ + uint8_t hmac[32]; + crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 32, hmac); + crypto_sha256_hmac_final(seed, slen, hmac); + uint32_t colour = 0; + uint32_t backlist[] = {0x00FF00}; + uint32_t dist = 0; + uint32_t min_dist = 40*40*3; + for(int i=0; i<32-3 && (dist < min_dist || i == 0);i++) { + uint8_t* rgb = &hmac[i]; + colour = ((uint32_t*) rgb)[0] & 0x0000ffffff; + uint32_t r, g, b = 0; + r = colour & 0x0000ff0000 >> 16; + g = colour & 0x000000ff00 >> 8; + b = colour & 0x00000000ff; + for(int j=0; j < 1 && dist < min_dist; j++) { + uint8_t* b_rgb = &((uint8_t*) &backlist[j])[1]; + dist = ((int) r - b_rgb[2])*(r - b_rgb[2]) + ((int)g - b_rgb[1])*((int)g - b_rgb[1]) + ((int)b - b_rgb[0])*((int)b - b_rgb[0]); + } + + } + return colour; +} static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, uint32_t * len, CTAP_credInfo * credInfo, CTAP_extensions * extensions) { @@ -617,7 +644,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au int but; - but = ctap2_user_presence_test(); + but = ctap2_user_presence_test(ctap_assertion_led_colour(authData->head.rpIdHash, 32)); if (CTAP2_ERR_PROCESSING == but) { authData->head.flags = (0 << 0); // User presence disabled @@ -880,7 +907,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt } if (MC.pinAuthEmpty) { - ret = ctap2_user_presence_test(); + ret = ctap2_user_presence_test(0); check_retr(ret); return ctap_is_pin_set() == 1 ? CTAP2_ERR_PIN_AUTH_INVALID : CTAP2_ERR_PIN_NOT_SET; } @@ -925,7 +952,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt { if ( check_credential_metadata(&excl_cred->credential.id, MC.pinAuthPresent, 1) == 0) { - ret = ctap2_user_presence_test(); + ret = ctap2_user_presence_test(0); check_retr(ret); printf1(TAG_MC, "Cred %d failed!\r\n",i); return CTAP2_ERR_CREDENTIAL_EXCLUDED; @@ -1738,6 +1765,7 @@ uint8_t ctap_cred_mgmt(CborEncoder * encoder, uint8_t * request, int length) return 0; } + uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) { CTAP_getAssertion GA; @@ -1752,7 +1780,8 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) if (GA.pinAuthEmpty) { - ret = ctap2_user_presence_test(); + uint32_t colour = ctap_assertion_led_colour(GA.clientDataHash, 32); + ret = ctap2_user_presence_test(colour); check_retr(ret); return ctap_is_pin_set() == 1 ? CTAP2_ERR_PIN_AUTH_INVALID : CTAP2_ERR_PIN_NOT_SET; } @@ -2285,7 +2314,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) break; case CTAP_RESET: printf1(TAG_CTAP,"CTAP_RESET\n"); - status = ctap2_user_presence_test(); + status = ctap2_user_presence_test(0); if (status == CTAP1_ERR_SUCCESS) { ctap_reset(); diff --git a/fido2/device.h b/fido2/device.h index 0c96c73..0784e83 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -87,6 +87,24 @@ int device_is_button_pressed(); */ int ctap_user_presence_test(uint32_t delay); +// +// Return 2 for disabled, 1 for user is present, 0 user not present, -1 if cancel is requested. +/** Test for user presence. + * Perform test that user is present. Returns status on user presence. This is used by FIDO and U2F layer + * to check if an operation should continue, or if the UP flag should be set. + * + * @param delay number of milliseconds to delay waiting for user before timeout. + * @param button_confirm_colour LED colour while waiting for confirmation. + * + * @return 2 - User presence is disabled. Operation should continue, but UP flag not set. + * 1 - User presence confirmed. Operation should continue, and UP flag is set. + * 0 - User presence is not confirmed. Operation should be denied. + * -1 - Operation was canceled. Do not continue, reset transaction state. + * + * *Optional*, the default implementation will return 1, unless a FIDO2 operation calls for no UP, where this will then return 2. +*/ +int ctap_user_presence_test_colour(uint32_t delay, uint32_t button_confirm_colour); + /** Disable the next user presence test. This is called by FIDO2 layer when a transaction * requests UP to be disabled. The next call to ctap_user_presence_test should return 2, * and then UP should be enabled again. diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index c8f487b..4096674 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -703,7 +703,11 @@ static int wait_for_button_release(uint32_t wait) return 0; } -int ctap_user_presence_test(uint32_t up_delay) +int ctap_user_presence_test(uint32_t up_delay) +{ + return ctap_user_presence_test_colour(up_delay, 0); +} +int ctap_user_presence_test_colour(uint32_t up_delay, uint32_t button_confirm_colour) { int ret; @@ -741,8 +745,7 @@ int ctap_user_presence_test(uint32_t up_delay) } // Set LED status and wait. - led_rgb(0xff3520); - + led_rgb(button_confirm_colour==0?0xff3520:button_confirm_colour); // Block and wait for some time. ret = wait_for_button_activate(up_delay); if (ret) return ret;