Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
5f3974a4e6 | |||
26adac1730 | |||
eab8b81c95 | |||
325396d518 | |||
6d04c86018 | |||
212f98e384 | |||
73f538dd0e | |||
a5f794c0ff | |||
f28cf9c6d0 |
@ -33,3 +33,8 @@ WARNING: This update may break previous registrations! This is because we fixed
|
|||||||
- Adds hmac-secret extension support. This extension is used for generating 32 or 64 byte symmetric keys using parameters from the platform and secrets on the authenticator. It's used by Windows Hello - - for offline authentication.
|
- Adds hmac-secret extension support. This extension is used for generating 32 or 64 byte symmetric keys using parameters from the platform and secrets on the authenticator. It's used by Windows Hello - - for offline authentication.
|
||||||
- Fix bug in FIDO auth, where setting the pin requires all previous registrations to use pin. Only UV bit needs to be cleared.
|
- Fix bug in FIDO auth, where setting the pin requires all previous registrations to use pin. Only UV bit needs to be cleared.
|
||||||
- Slightly change serial emulation USB descriptor to make it less abused by Linux Modem Manager.
|
- Slightly change serial emulation USB descriptor to make it less abused by Linux Modem Manager.
|
||||||
|
|
||||||
|
## [2.2.0] - 2019-04-17
|
||||||
|
|
||||||
|
- Fixes the ordering of keys encoded in CBOR maps to be canonical ordering. They previously were not ordered in any particular way and caused issues for Chrome. #170
|
||||||
|
- Fixes CTAP2 implementation to accept credential IDs created by the CTAP1 implementation. So registering with U2F and later authenticating with FIDO2 should work.
|
||||||
|
@ -1 +1 @@
|
|||||||
2.1.0
|
2.2.0
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#define COSE_KEY_KTY_EC2 2
|
#define COSE_KEY_KTY_EC2 2
|
||||||
#define COSE_KEY_CRV_P256 1
|
#define COSE_KEY_CRV_P256 1
|
||||||
|
|
||||||
|
#define COSE_ALG_ES256 -7
|
||||||
#define COSE_ALG_ES256 -7
|
#define COSE_ALG_ECDH_ES_HKDF_256 -25
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
29
fido2/ctap.c
29
fido2/ctap.c
@ -466,12 +466,11 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
|||||||
count = auth_data_update_count(&authData->head);
|
count = auth_data_update_count(&authData->head);
|
||||||
|
|
||||||
device_set_status(CTAPHID_STATUS_UPNEEDED);
|
device_set_status(CTAPHID_STATUS_UPNEEDED);
|
||||||
// if NFC - not need to click a button
|
|
||||||
int but = 1;
|
int but;
|
||||||
if(!device_is_nfc())
|
|
||||||
{
|
but = ctap_user_presence_test();
|
||||||
but = ctap_user_presence_test();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!but)
|
if (!but)
|
||||||
{
|
{
|
||||||
@ -702,6 +701,14 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
|
|||||||
printf2(TAG_ERR,"error, parse_make_credential failed\n");
|
printf2(TAG_ERR,"error, parse_make_credential failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (MC.pinAuthEmpty)
|
||||||
|
{
|
||||||
|
if (!ctap_user_presence_test())
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_OPERATION_DENIED;
|
||||||
|
}
|
||||||
|
return ctap_is_pin_set() == 1 ? CTAP2_ERR_PIN_INVALID : CTAP2_ERR_PIN_NOT_SET;
|
||||||
|
}
|
||||||
if ((MC.paramsParsed & MC_requiredMask) != MC_requiredMask)
|
if ((MC.paramsParsed & MC_requiredMask) != MC_requiredMask)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"error, required parameter(s) for makeCredential are missing\n");
|
printf2(TAG_ERR,"error, required parameter(s) for makeCredential are missing\n");
|
||||||
@ -1133,6 +1140,14 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GA.pinAuthEmpty)
|
||||||
|
{
|
||||||
|
if (!ctap_user_presence_test())
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_OPERATION_DENIED;
|
||||||
|
}
|
||||||
|
return ctap_is_pin_set() == 1 ? CTAP2_ERR_PIN_INVALID : CTAP2_ERR_PIN_NOT_SET;
|
||||||
|
}
|
||||||
if (GA.pinAuthPresent)
|
if (GA.pinAuthPresent)
|
||||||
{
|
{
|
||||||
ret = verify_pin_auth(GA.pinAuth, GA.clientDataHash);
|
ret = verify_pin_auth(GA.pinAuth, GA.clientDataHash);
|
||||||
@ -1460,7 +1475,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
|
|
||||||
ret = cbor_encode_int(&map, RESP_keyAgreement);
|
ret = cbor_encode_int(&map, RESP_keyAgreement);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = ctap_add_cose_key(&map, KEY_AGREEMENT_PUB, KEY_AGREEMENT_PUB+32, PUB_KEY_CRED_PUB_KEY, COSE_ALG_ES256);
|
ret = ctap_add_cose_key(&map, KEY_AGREEMENT_PUB, KEY_AGREEMENT_PUB+32, PUB_KEY_CRED_PUB_KEY, COSE_ALG_ECDH_ES_HKDF_256);
|
||||||
check_retr(ret);
|
check_retr(ret);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
10
fido2/ctap.h
10
fido2/ctap.h
@ -243,6 +243,11 @@ typedef struct
|
|||||||
|
|
||||||
uint8_t pinAuth[16];
|
uint8_t pinAuth[16];
|
||||||
uint8_t pinAuthPresent;
|
uint8_t pinAuthPresent;
|
||||||
|
// pinAuthEmpty is true iff an empty bytestring was provided as pinAuth.
|
||||||
|
// This is exclusive with |pinAuthPresent|. It exists because an empty
|
||||||
|
// pinAuth is a special signal to block for touch. See
|
||||||
|
// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#using-pinToken-in-authenticatorMakeCredential
|
||||||
|
uint8_t pinAuthEmpty;
|
||||||
int pinProtocol;
|
int pinProtocol;
|
||||||
CTAP_extensions extensions;
|
CTAP_extensions extensions;
|
||||||
|
|
||||||
@ -266,6 +271,11 @@ typedef struct
|
|||||||
|
|
||||||
uint8_t pinAuth[16];
|
uint8_t pinAuth[16];
|
||||||
uint8_t pinAuthPresent;
|
uint8_t pinAuthPresent;
|
||||||
|
// pinAuthEmpty is true iff an empty bytestring was provided as pinAuth.
|
||||||
|
// This is exclusive with |pinAuthPresent|. It exists because an empty
|
||||||
|
// pinAuth is a special signal to block for touch. See
|
||||||
|
// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#using-pinToken-in-authenticatorGetAssertion
|
||||||
|
uint8_t pinAuthEmpty;
|
||||||
int pinProtocol;
|
int pinProtocol;
|
||||||
|
|
||||||
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
||||||
|
@ -823,14 +823,22 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
|
|||||||
ret = parse_options(&map, &MC->credInfo.rk, &MC->uv, &MC->up);
|
ret = parse_options(&map, &MC->credInfo.rk, &MC->uv, &MC->up);
|
||||||
check_retr(ret);
|
check_retr(ret);
|
||||||
break;
|
break;
|
||||||
case MC_pinAuth:
|
case MC_pinAuth: {
|
||||||
printf1(TAG_MC,"CTAP_pinAuth\n");
|
printf1(TAG_MC,"CTAP_pinAuth\n");
|
||||||
|
|
||||||
|
size_t pinSize;
|
||||||
|
if (cbor_value_get_type(&map) == CborByteStringType &&
|
||||||
|
cbor_value_get_string_length(&map, &pinSize) == CborNoError &&
|
||||||
|
pinSize == 0)
|
||||||
|
{
|
||||||
|
MC->pinAuthEmpty = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = parse_fixed_byte_string(&map, MC->pinAuth, 16);
|
ret = parse_fixed_byte_string(&map, MC->pinAuth, 16);
|
||||||
if (CTAP1_ERR_INVALID_LENGTH != ret) // damn microsoft
|
if (CTAP1_ERR_INVALID_LENGTH != ret) // damn microsoft
|
||||||
{
|
{
|
||||||
check_retr(ret);
|
check_retr(ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -838,6 +846,7 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
|
|||||||
}
|
}
|
||||||
MC->pinAuthPresent = 1;
|
MC->pinAuthPresent = 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case MC_pinProtocol:
|
case MC_pinProtocol:
|
||||||
printf1(TAG_MC,"CTAP_pinProtocol\n");
|
printf1(TAG_MC,"CTAP_pinProtocol\n");
|
||||||
if (cbor_value_get_type(&map) == CborIntegerType)
|
if (cbor_value_get_type(&map) == CborIntegerType)
|
||||||
@ -1055,9 +1064,18 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
|
|||||||
ret = parse_options(&map, &GA->rk, &GA->uv, &GA->up);
|
ret = parse_options(&map, &GA->rk, &GA->uv, &GA->up);
|
||||||
check_retr(ret);
|
check_retr(ret);
|
||||||
break;
|
break;
|
||||||
case GA_pinAuth:
|
case GA_pinAuth: {
|
||||||
printf1(TAG_GA,"CTAP_pinAuth\n");
|
printf1(TAG_GA,"CTAP_pinAuth\n");
|
||||||
|
|
||||||
|
size_t pinSize;
|
||||||
|
if (cbor_value_get_type(&map) == CborByteStringType &&
|
||||||
|
cbor_value_get_string_length(&map, &pinSize) == CborNoError &&
|
||||||
|
pinSize == 0)
|
||||||
|
{
|
||||||
|
GA->pinAuthEmpty = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = parse_fixed_byte_string(&map, GA->pinAuth, 16);
|
ret = parse_fixed_byte_string(&map, GA->pinAuth, 16);
|
||||||
if (CTAP1_ERR_INVALID_LENGTH != ret) // damn microsoft
|
if (CTAP1_ERR_INVALID_LENGTH != ret) // damn microsoft
|
||||||
{
|
{
|
||||||
@ -1073,6 +1091,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
|
|||||||
GA->pinAuthPresent = 1;
|
GA->pinAuthPresent = 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GA_pinProtocol:
|
case GA_pinProtocol:
|
||||||
printf1(TAG_GA,"CTAP_pinProtocol\n");
|
printf1(TAG_GA,"CTAP_pinProtocol\n");
|
||||||
if (cbor_value_get_type(&map) == CborIntegerType)
|
if (cbor_value_get_type(&map) == CborIntegerType)
|
||||||
|
@ -81,4 +81,4 @@ cbor:
|
|||||||
cd ../../tinycbor/ && make clean
|
cd ../../tinycbor/ && make clean
|
||||||
cd ../../tinycbor/ && make CC="$(CC)" AR=$(AR) \
|
cd ../../tinycbor/ && make CC="$(CC)" AR=$(AR) \
|
||||||
LDFLAGS="$(LDFLAGS_LIB)" \
|
LDFLAGS="$(LDFLAGS_LIB)" \
|
||||||
CFLAGS="$(CFLAGS)"
|
CFLAGS="$(CFLAGS) -Os"
|
||||||
|
@ -111,13 +111,13 @@ void device_init()
|
|||||||
{
|
{
|
||||||
|
|
||||||
hw_init(LOW_FREQUENCY);
|
hw_init(LOW_FREQUENCY);
|
||||||
isLowFreq = 0;
|
|
||||||
|
|
||||||
haveNFC = nfc_init();
|
haveNFC = nfc_init();
|
||||||
|
|
||||||
if (haveNFC)
|
if (haveNFC)
|
||||||
{
|
{
|
||||||
printf1(TAG_NFC, "Have NFC\r\n");
|
printf1(TAG_NFC, "Have NFC\r\n");
|
||||||
|
isLowFreq = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -460,6 +460,10 @@ static int handle_packets()
|
|||||||
int ctap_user_presence_test()
|
int ctap_user_presence_test()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
if (device_is_nfc())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
#if SKIP_BUTTON_CHECK_WITH_DELAY
|
#if SKIP_BUTTON_CHECK_WITH_DELAY
|
||||||
int i=500;
|
int i=500;
|
||||||
while(i--)
|
while(i--)
|
||||||
|
@ -496,9 +496,9 @@ void nfc_process_iblock(uint8_t * buf, int len)
|
|||||||
// WTX_on(WTX_TIME_DEFAULT);
|
// WTX_on(WTX_TIME_DEFAULT);
|
||||||
// SystemClock_Config_LF32();
|
// SystemClock_Config_LF32();
|
||||||
// delay(300);
|
// delay(300);
|
||||||
device_set_clock_rate(DEVICE_LOW_POWER_FAST);;
|
if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_FAST);;
|
||||||
u2f_request_nfc(&buf[1], len, &ctap_resp);
|
u2f_request_nfc(&buf[1], len, &ctap_resp);
|
||||||
device_set_clock_rate(DEVICE_LOW_POWER_IDLE);;
|
if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_IDLE);;
|
||||||
// if (!WTX_off())
|
// if (!WTX_off())
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user