Compare commits

..

9 Commits
2.2.0 ... 2.2.1

Author SHA1 Message Date
5f3974a4e6 Merge pull request #182 from solokeys/nfc_adjustments
Nfc adjustments
2019-04-23 19:42:14 -04:00
26adac1730 size optimize tinycbor 2019-04-23 19:17:18 -04:00
eab8b81c95 include nfc in user presence test 2019-04-23 14:05:18 -04:00
325396d518 dont change clock freq if powered 2019-04-23 13:54:23 -04:00
6d04c86018 update lowFreq flag correctly 2019-04-23 13:54:10 -04:00
212f98e384 Merge pull request #179 from agl/pinfixes
Couple of fixes for PIN support
2019-04-22 16:11:34 -04:00
73f538dd0e Fix COSE type of key-agreement keys.
The key-agreement keys in the PIN protocol use COSE type -25. I'm not
sure if that's written down anywhere, but it's what everything else does
and it's an ECDH type rather than an ECDSA type.
2019-04-20 16:45:04 -07:00
a5f794c0ff Handle empty pinAuth fields.
CTAP2 specifies that an empty pinAuth field is special: it indicates
that the device should block for touch, i.e. it's just a way of letting
a user select from multiple authenticators[1].

This change handles empty pinAuth fields in GetAssertion and
MakeCredential commands.

[1] https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#using-pinToken-in-authenticatorMakeCredential
2019-04-20 16:26:32 -07:00
f28cf9c6d0 new release 2019-04-18 20:41:18 -07:00
9 changed files with 70 additions and 17 deletions

View File

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

View File

@ -1 +1 @@
2.1.0 2.2.0

View File

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

View File

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

View File

@ -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];

View File

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

View File

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

View File

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

View File

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