Compare commits

...

6 Commits

Author SHA1 Message Date
Conor Patrick
8955a1ccf4 default up to enabled 2019-09-17 00:06:45 +08:00
Conor Patrick
16f07bfc95 allow in bootloader as well 2019-09-16 17:12:09 +08:00
Conor Patrick
0945ad264c add get_version command to hid 2019-09-16 17:00:30 +08:00
Conor Patrick
b20ca7c5f7 delete old code 2019-09-16 17:00:13 +08:00
Conor Patrick
bc73ce8d21 allow get_assertion with disabled UP 2019-09-16 16:25:58 +08:00
Conor Patrick
2051ddb180 properly check the rpId in request 2019-09-16 15:33:38 +08:00
9 changed files with 63 additions and 160 deletions

View File

@ -438,7 +438,11 @@ static int ctap2_user_presence_test()
{ {
device_set_status(CTAPHID_STATUS_UPNEEDED); device_set_status(CTAPHID_STATUS_UPNEEDED);
int ret = ctap_user_presence_test(CTAP2_UP_DELAY_MS); int ret = ctap_user_presence_test(CTAP2_UP_DELAY_MS);
if ( ret > 0 ) if ( ret > 1 )
{
return CTAP2_ERR_PROCESSING;
}
else if ( ret > 0 )
{ {
return CTAP1_ERR_SUCCESS; return CTAP1_ERR_SUCCESS;
} }
@ -482,11 +486,19 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
int but; int but;
but = ctap2_user_presence_test(CTAP2_UP_DELAY_MS); but = ctap2_user_presence_test(CTAP2_UP_DELAY_MS);
check_retr(but); if (CTAP2_ERR_PROCESSING == but)
{
authData->head.flags = (0 << 0); // User presence disabled
}
else
{
check_retr(but);
authData->head.flags = (1 << 0); // User presence
}
device_set_status(CTAPHID_STATUS_PROCESSING); device_set_status(CTAPHID_STATUS_PROCESSING);
authData->head.flags = (1 << 0); // User presence
authData->head.flags |= (ctap_is_pin_set() << 2); authData->head.flags |= (ctap_is_pin_set() << 2);
@ -670,7 +682,16 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d
switch(desc->type) switch(desc->type)
{ {
case PUB_KEY_CRED_PUB_KEY: case PUB_KEY_CRED_PUB_KEY:
make_auth_tag(desc->credential.id.rpIdHash, desc->credential.id.nonce, desc->credential.id.count, tag); crypto_sha256_init();
crypto_sha256_update(rp->id, rp->size);
crypto_sha256_final(rpIdHash);
printf1(TAG_RED,"rpId: %s\r\n", rp->id); dump_hex1(TAG_RED,rp->id, rp->size);
if (memcmp(desc->credential.id.rpIdHash, rpIdHash, 32) != 0)
{
return 0;
}
make_auth_tag(rpIdHash, desc->credential.id.nonce, desc->credential.id.count, tag);
return (memcmp(desc->credential.id.tag, tag, CREDENTIAL_TAG_SIZE) == 0); return (memcmp(desc->credential.id.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
break; break;
case PUB_KEY_CRED_CTAP1: case PUB_KEY_CRED_CTAP1:
@ -734,7 +755,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
} }
} }
if (MC.up) if (MC.up == 1 || MC.up == 0)
{ {
return CTAP2_ERR_INVALID_OPTION; return CTAP2_ERR_INVALID_OPTION;
} }
@ -1227,8 +1248,9 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
else else
#endif #endif
{ {
device_disable_up(GA.up == 0);
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, &auth_data_buf_sz, NULL); ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, &auth_data_buf_sz, NULL);
device_disable_up(false);
check_retr(ret); check_retr(ret);
((CTAP_authDataHeader *)auth_data_buf)->flags &= ~(1 << 2); ((CTAP_authDataHeader *)auth_data_buf)->flags &= ~(1 << 2);

View File

@ -715,6 +715,7 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
CborValue it,map; CborValue it,map;
memset(MC, 0, sizeof(CTAP_makeCredential)); memset(MC, 0, sizeof(CTAP_makeCredential));
MC->up = 0xff;
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it); ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
check_retr(ret); check_retr(ret);
@ -1010,6 +1011,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
memset(GA, 0, sizeof(CTAP_getAssertion)); memset(GA, 0, sizeof(CTAP_getAssertion));
GA->creds = getAssertionState.creds; // Save stack memory GA->creds = getAssertionState.creds; // Save stack memory
GA->up = 0xff;
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it); ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
check_ret(ret); check_ret(ret);

View File

@ -16,6 +16,7 @@
#include "util.h" #include "util.h"
#include "log.h" #include "log.h"
#include "extensions.h" #include "extensions.h"
#include "version.h"
// move custom SHA512 command out, // move custom SHA512 command out,
// and the following headers too // and the following headers too
@ -729,155 +730,22 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
is_busy = 0; is_busy = 0;
break; break;
#endif #endif
#if defined(SOLO_HACKER) && (DEBUG_LEVEL > 0) && (!IS_BOOTLOADER == 1)
case CTAPHID_PROBE:
/* case CTAPHID_GETVERSION:
* Expects CBOR-serialized data of the form printf1(TAG_HID,"CTAPHID_GETVERSION\n");
* {"subcommand": "hash_type", "data": b"the_data"}
* with hash_type in SHA256, SHA512
*/
// some random logging
printf1(TAG_HID,"CTAPHID_PROBE\n");
// initialise CTAP response object
ctap_response_init(&ctap_resp); ctap_response_init(&ctap_resp);
// initialise write buffer
ctaphid_write_buffer_init(&wb); ctaphid_write_buffer_init(&wb);
wb.cid = cid; wb.cid = cid;
wb.cmd = CTAPHID_PROBE; wb.cmd = CTAPHID_GETVERSION;
wb.bcnt = 3;
// prepare parsing (or halt) ctap_buffer[0] = SOLO_VERSION_MAJ;
int ret; ctap_buffer[1] = SOLO_VERSION_MIN;
CborParser parser; ctap_buffer[2] = SOLO_VERSION_PATCH;
CborValue it, map; ctaphid_write(&wb, &ctap_buffer, 3);
ret = cbor_parser_init(
ctap_buffer, (size_t) buffer_len(),
// strictly speaking, CTAP is not RFC canonical...
CborValidateCanonicalFormat,
&parser, &it);
check_hardcore(ret);
CborType type = cbor_value_get_type(&it);
if (type != CborMapType) exit(1);
ret = cbor_value_enter_container(&it,&map);
check_hardcore(ret);
size_t map_length = 0;
ret = cbor_value_get_map_length(&it, &map_length);
if (map_length != 2) exit(1);
// parse subcommand (or halt)
CborValue val;
ret = cbor_value_map_find_value(&it, "subcommand", &val);
check_hardcore(ret);
if (!cbor_value_is_text_string(&val))
exit(1);
int sha_version = 0;
bool found = false;
if (!found) {
ret = cbor_value_text_string_equals(
&val, "SHA256", &found);
check_hardcore(ret);
if (found)
sha_version = 256;
}
if (!found) {
ret = cbor_value_text_string_equals(
&val, "SHA512", &found);
check_hardcore(ret);
if (found)
sha_version = 512;
}
if (sha_version == 0)
exit(1);
// parse data (or halt)
ret = cbor_value_map_find_value(&it, "data", &val);
check_hardcore(ret);
if (!cbor_value_is_byte_string(&val))
exit(1);
size_t data_length = 0;
ret = cbor_value_calculate_string_length(&val, &data_length);
check_hardcore(ret);
if (data_length > 6*1024)
exit(1);
unsigned char data[6*1024];
ret = cbor_value_copy_byte_string (
&val, &data[0], &data_length, &val);
check_hardcore(ret);
// execute subcommand
if (sha_version == 256) {
// calculate hash
crypto_sha256_init();
crypto_sha256_update(data, data_length);
crypto_sha256_final(ctap_buffer);
// write output
wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes
ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ);
}
if (sha_version == 512) {
// calculate hash
crypto_sha512_init();
crypto_sha512_update(data, data_length);
crypto_sha512_final(ctap_buffer);
// write output
wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes
ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ);
}
// finalize
ctaphid_write(&wb, NULL, 0); ctaphid_write(&wb, NULL, 0);
is_busy = 0; is_busy = 0;
break; break;
/*
case CTAPHID_SHA256:
// some random logging
printf1(TAG_HID,"CTAPHID_SHA256\n");
// initialise CTAP response object
ctap_response_init(&ctap_resp);
// initialise write buffer
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_SHA256;
wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes
// calculate hash
crypto_sha256_init();
crypto_sha256_update(ctap_buffer, buffer_len());
crypto_sha256_final(ctap_buffer);
// copy to output
ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ);
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
case CTAPHID_SHA512:
// some random logging
printf1(TAG_HID,"CTAPHID_SHA512\n");
// initialise CTAP response object
ctap_response_init(&ctap_resp);
// initialise write buffer
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_SHA512;
wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes
// calculate hash
crypto_sha512_init();
crypto_sha512_update(ctap_buffer, buffer_len());
crypto_sha512_final(ctap_buffer);
// copy to output
ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ);
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
*/
#endif
default: default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND); ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);

View File

@ -28,6 +28,7 @@
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51) #define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52) #define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
#define CTAPHID_GETRNG (TYPE_INIT | 0x60) #define CTAPHID_GETRNG (TYPE_INIT | 0x60)
#define CTAPHID_GETVERSION (TYPE_INIT | 0x61)
// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0 // reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0
#define CTAPHID_PROBE (TYPE_INIT | 0x70) #define CTAPHID_PROBE (TYPE_INIT | 0x70)

View File

@ -53,7 +53,7 @@ void device_set_status(uint32_t status);
int device_is_button_pressed(); int device_is_button_pressed();
// Test for user presence // Test for user presence
// Return 1 for user is present, 0 user not present, -1 if cancel is requested. // Return 2 for disabled, 1 for user is present, 0 user not present, -1 if cancel is requested.
int ctap_user_presence_test(uint32_t delay); int ctap_user_presence_test(uint32_t delay);
// Generate @num bytes of random numbers to @dest // Generate @num bytes of random numbers to @dest
@ -106,7 +106,7 @@ void device_set_clock_rate(DEVICE_CLOCK_RATE param);
#define NFC_IS_AVAILABLE 2 #define NFC_IS_AVAILABLE 2
int device_is_nfc(); int device_is_nfc();
void request_from_nfc(bool request_active); void device_disable_up(bool request_active);
void device_init_button(); void device_init_button();

View File

@ -118,9 +118,9 @@ void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONS
if (!header) if (!header)
return; return;
request_from_nfc(true); // disable presence test device_disable_up(true); // disable presence test
u2f_request_ex((APDU_HEADER *)header, data, datalen, resp); u2f_request_ex((APDU_HEADER *)header, data, datalen, resp);
request_from_nfc(false); // enable presence test device_disable_up(false); // enable presence test
} }
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)

View File

@ -26,6 +26,7 @@
#define RK_NUM 50 #define RK_NUM 50
bool use_udp = true; bool use_udp = true;
static bool _up_disabled = false;
struct ResidentKeyStore { struct ResidentKeyStore {
CTAP_residentKey rks[RK_NUM]; CTAP_residentKey rks[RK_NUM];
@ -299,6 +300,10 @@ void ctaphid_write_block(uint8_t * data)
int ctap_user_presence_test(uint32_t d) int ctap_user_presence_test(uint32_t d)
{ {
if (_up_disabled)
{
return 2;
}
return 1; return 1;
} }
@ -633,10 +638,9 @@ int device_is_nfc()
return 0; return 0;
} }
void device_disable_up(bool disable)
void request_from_nfc(bool request_active)
{ {
_up_disabled = disable;
} }
void device_set_clock_rate(DEVICE_CLOCK_RATE param) void device_set_clock_rate(DEVICE_CLOCK_RATE param)

View File

@ -45,7 +45,7 @@ uint32_t __last_update = 0;
extern PCD_HandleTypeDef hpcd; extern PCD_HandleTypeDef hpcd;
static int _NFC_status = 0; static int _NFC_status = 0;
static bool isLowFreq = 0; static bool isLowFreq = 0;
static bool _RequestComeFromNFC = false; static bool _up_disabled = false;
// #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) // #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
static int is_physical_button_pressed() static int is_physical_button_pressed()
@ -92,8 +92,8 @@ static void edge_detect_touch_button()
} }
void request_from_nfc(bool request_active) { void device_disable_up(bool disable) {
_RequestComeFromNFC = request_active; _up_disabled = disable;
} }
// Timer6 overflow handler. happens every ~90ms. // Timer6 overflow handler. happens every ~90ms.
@ -582,11 +582,17 @@ static int wait_for_button_release(uint32_t wait)
int ctap_user_presence_test(uint32_t up_delay) int ctap_user_presence_test(uint32_t up_delay)
{ {
int ret; int ret;
if (device_is_nfc() == NFC_IS_ACTIVE || _RequestComeFromNFC)
if (device_is_nfc() == NFC_IS_ACTIVE)
{ {
return 1; return 1;
} }
if (_up_disabled)
{
return 2;
}
#if SKIP_BUTTON_CHECK_WITH_DELAY #if SKIP_BUTTON_CHECK_WITH_DELAY
int i=500; int i=500;
while(i--) while(i--)

View File

@ -731,10 +731,10 @@ void apdu_process(uint8_t buf0, uint8_t *apduptr, APDU_STRUCT *apdu)
printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp()); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp());
// WTX_on(WTX_TIME_DEFAULT); // WTX_on(WTX_TIME_DEFAULT);
request_from_nfc(true); device_disable_up(true);
ctap_response_init(&ctap_resp); ctap_response_init(&ctap_resp);
status = ctap_request(apdu->data, apdu->lc, &ctap_resp); status = ctap_request(apdu->data, apdu->lc, &ctap_resp);
request_from_nfc(false); device_disable_up(false);
// if (!WTX_off()) // if (!WTX_off())
// return; // return;