make led colour depend on credential

This commit is contained in:
shimun 2020-06-09 20:12:55 +02:00
parent 299e91b91b
commit 4743fd2326
Signed by: shimun
GPG Key ID: E81D8382DC2F971B
3 changed files with 61 additions and 11 deletions

View File

@ -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();

View File

@ -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.

View File

@ -704,6 +704,10 @@ static int wait_for_button_release(uint32_t wait)
}
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;