pass fido2 tests

This commit is contained in:
Conor Patrick
2018-10-28 16:30:55 -04:00
parent 2f911368da
commit 2fd96f8e4b
23 changed files with 900 additions and 318 deletions

View File

@@ -26,6 +26,7 @@
#include "cbor.h"
#include "ctap.h"
#include "ctaphid.h"
#include "ctap_parse.h"
#include "ctap_errors.h"
#include "cose_key.h"
@@ -43,6 +44,7 @@ uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
uint8_t KEY_AGREEMENT_PUB[64];
static uint8_t KEY_AGREEMENT_PRIV[32];
static uint8_t PIN_CODE_HASH[32];
static int8_t PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
AuthenticatorState STATE;
@@ -264,11 +266,11 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input,
return 0;
}
void make_auth_tag(struct rpId * rp, CTAP_userEntity * user, uint32_t count, uint8_t * tag)
void make_auth_tag(uint8_t * nonce, CTAP_userEntity * user, uint32_t count, uint8_t * tag)
{
uint8_t hashbuf[32];
crypto_sha256_hmac_init(NULL, 0, hashbuf);
crypto_sha256_update(rp->id, rp->size);
crypto_sha256_update(nonce, CREDENTIAL_NONCE_SIZE);
crypto_sha256_update(user->id, user->id_size);
crypto_sha256_update(user->name, strnlen((const char*)user->name, USER_NAME_LIMIT));
crypto_sha256_update((uint8_t*)&count, 4);
@@ -283,21 +285,19 @@ static uint32_t auth_data_update_count(CTAP_authDataHeader * authData)
if (count == 0) // count 0 will indicate invalid token
{
count = ctap_atomic_count( 0 );
}
uint8_t * byte = (uint8_t*) &authData->signCount;
*byte++ = count & 0xff;
count = count >> 8;
*byte++ = count & 0xff;
count = count >> 8;
*byte++ = count & 0xff;
count = count >> 8;
*byte++ = count & 0xff;
*byte++ = (count >> 0) & 0xff;
*byte++ = (count >> 8) & 0xff;
*byte++ = (count >> 16) & 0xff;
*byte++ = (count >> 24) & 0xff;
return count;
}
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype)
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz)
{
CborEncoder cose_key;
int auth_data_sz, ret;
@@ -318,10 +318,24 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
count = auth_data_update_count(&authData->head);
authData->head.flags = (ctap_user_presence_test() << 0);
device_set_status(CTAPHID_STATUS_UPNEEDED);
int but = ctap_user_presence_test();
if (!but)
{
return CTAP2_ERR_OPERATION_DENIED;
}
else if (but < 0) // Cancel
{
return CTAP2_ERR_KEEPALIVE_CANCEL;
}
device_set_status(CTAPHID_STATUS_PROCESSING);
authData->head.flags = (but << 0);
authData->head.flags |= (ctap_user_verification(0) << 2);
if (credtype != 0)
{
// add attestedCredentialData
@@ -338,19 +352,19 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
#else
memset((uint8_t*)&authData->attest.credential, 0, sizeof(struct Credential));
// Make a tag we can later check to make sure this is a token we made
make_auth_tag(rp, user, count, authData->attest.credential.tag);
ctap_generate_rng(authData->attest.credential.nonce, CREDENTIAL_NONCE_SIZE);
memmove(&authData->attest.credential.enc.user, user, sizeof(CTAP_userEntity)); //TODO encrypt this
authData->attest.credential.enc.count = count;
// Make a tag we can later check to make sure this is a token we made
make_auth_tag(authData->attest.credential.nonce, user, count, authData->attest.credential.tag);
crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL);
crypto_aes256_encrypt((uint8_t*)&authData->attest.credential.enc, CREDENTIAL_ENC_SIZE);
ctap_generate_cose_key(&cose_key, (uint8_t*)&authData->attest.credential, sizeof(struct Credential), credtype, algtype);
printf1(TAG_MC,"COSE_KEY: "); dump_hex1(TAG_MC, cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf));
auth_data_sz = sizeof(CTAP_authData) + cbor_encoder_get_buffer_size(&cose_key, cose_key_buf);
#endif
@@ -367,7 +381,8 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
check_ret(ret);
}
return auth_data_sz;
if (sz) *sz = auth_data_sz;
return 0;
}
@@ -419,7 +434,6 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa
crypto_sha256_update(clientDataHash, CLIENT_DATA_HASH_SIZE);
crypto_sha256_final(hashbuf);
printf1(TAG_GREEN, "sha256: "); dump_hex1(TAG_DUMP,hashbuf,32);
crypto_ecc256_sign(hashbuf, 32, sigbuf);
return ctap_encode_der_sig(sigbuf,sigder);
@@ -471,13 +485,8 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc)
{
uint8_t tag[16];
if (desc->type != PUB_KEY_CRED_PUB_KEY)
{
printf1(TAG_GA,"unsupported credential type: %d\n", desc->type);
return 0;
}
make_auth_tag(rp, &desc->credential.enc.user, desc->credential.enc.count, tag);
make_auth_tag(desc->credential.nonce, &desc->credential.enc.user, desc->credential.enc.count, tag);
return (memcmp(desc->credential.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
}
@@ -519,6 +528,12 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
}
}
if (MC.up)
{
return CTAP2_ERR_INVALID_OPTION;
}
crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL);
for (i = 0; i < MC.excludeListSize; i++)
{
ret = parse_credential_descriptor(&MC.excludeList, excl_cred);
@@ -528,8 +543,11 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
}
check_retr(ret);
crypto_aes256_reset_iv(NULL);
crypto_aes256_decrypt((uint8_t*)& excl_cred->credential.enc, CREDENTIAL_ENC_SIZE);
if (ctap_authenticate_credential(&MC.rp, excl_cred))
{
printf1(TAG_MC, "Cred %d failed!\r\n",i);
return CTAP2_ERR_CREDENTIAL_EXCLUDED;
}
@@ -540,9 +558,11 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
CborEncoder map;
ret = cbor_encoder_create_map(encoder, &map, 3);
check_ret(ret);
int32_t auth_data_sz;
int auth_data_sz = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf),
&MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier);
ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf),
&MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz);
check_retr(ret);
crypto_ecc256_load_attestation_key();
int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder);
@@ -724,11 +744,6 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
crypto_ecc256_load_key((uint8_t*)&cred->credential, sizeof(struct Credential), NULL, 0);
/*printf1(TAG_GREEN,"auth_data_buf: "); dump_hex1(TAG_DUMP, auth_data_buf, sizeof(CTAP_authDataHeader));*/
/*printf1(TAG_GREEN,"clientdatahash: "); dump_hex1(TAG_DUMP, clientDataHash, 32);*/
/*printf1(TAG_GREEN,"credential: # %d\n", cred->credential.enc.count);*/
/*dump_hex1(TAG_DUMP, clientDataHash, 32);*/
int sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
{
@@ -801,12 +816,16 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
}
}
if (!GA.rp.size || !GA.clientDataHashPresent)
{
return CTAP2_ERR_MISSING_PARAMETER;
}
CborEncoder map;
ret = cbor_encoder_create_map(encoder, &map, 5);
check_ret(ret);
ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0);
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL);
check_retr(ret);
printf1(TAG_GA, "ALLOW_LIST has %d creds\n", GA.credLen);
/*for (int j = 0; j < GA.credLen; j++)*/
@@ -834,13 +853,13 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
else
{
printf2(TAG_ERR,"Error, no authentic credential\n");
return CTAP2_ERR_CREDENTIAL_NOT_VALID;
return CTAP2_ERR_NO_CREDENTIALS;
}
printf1(TAG_RED,"resulting order of creds:\n");
printf1(TAG_GA,"resulting order of creds:\n");
for (int j = 0; j < GA.credLen; j++)
{
printf1(TAG_RED,"CRED ID (# %d)\n", GA.creds[j].credential.enc.count);
printf1(TAG_GA,"CRED ID (# %d)\n", GA.creds[j].credential.enc.count);
}
{
@@ -861,6 +880,18 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
return 0;
}
// Return how many trailing zeros in a buffer
static int trailing_zeros(uint8_t * buf, int indx)
{
int c = 0;
while(0==buf[indx] && indx)
{
indx--;
c++;
}
return c;
}
uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platform_pubkey, uint8_t * pinAuth, uint8_t * pinHashEnc)
{
uint8_t shared_secret[32];
@@ -876,7 +907,11 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
{
if (ctap_device_locked())
{
return CTAP2_ERR_OPERATION_DENIED;
return CTAP2_ERR_PIN_BLOCKED;
}
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
}
@@ -911,25 +946,31 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
crypto_aes256_decrypt(pinEnc, len);
printf1(TAG_CP,"new pin: %s\n", pinEnc);
ret = strnlen((const char *)pinEnc, NEW_PIN_ENC_MAX_SIZE);
if (ret == NEW_PIN_ENC_MAX_SIZE)
ret = trailing_zeros(pinEnc, NEW_PIN_ENC_MIN_SIZE - 1);
ret = NEW_PIN_ENC_MIN_SIZE - ret;
if (ret < NEW_PIN_MIN_SIZE || ret >= NEW_PIN_MAX_SIZE)
{
printf2(TAG_ERR,"No NULL terminator in new pin string\n");
return CTAP1_ERR_OTHER;
}
else if (ret < 4)
{
printf2(TAG_ERR,"new PIN is too short\n");
printf2(TAG_ERR,"new PIN is too short or too long [%d bytes]\n", ret);
return CTAP2_ERR_PIN_POLICY_VIOLATION;
}
else
{
printf1(TAG_CP,"new pin: %s [%d bytes]\n", pinEnc, ret);
dump_hex1(TAG_CP, pinEnc, ret);
}
if (ctap_is_pin_set())
{
if (ctap_device_locked())
{
return CTAP2_ERR_OPERATION_DENIED;
return CTAP2_ERR_PIN_BLOCKED;
}
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
crypto_aes256_reset_iv(NULL);
crypto_aes256_decrypt(pinHashEnc, 16);
@@ -937,6 +978,10 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
{
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
ctap_decrement_pin_attempts();
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
return CTAP2_ERR_PIN_INVALID;
}
else
@@ -976,6 +1021,10 @@ uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubke
// Generate new keyAgreement pair
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
ctap_decrement_pin_attempts();
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
return CTAP2_ERR_PIN_INVALID;
}
@@ -995,6 +1044,20 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
uint8_t pinTokenEnc[PIN_TOKEN_SIZE];
int ret = ctap_parse_client_pin(&CP,request,length);
switch(CP.subCommand)
{
case CP_cmdSetPin:
case CP_cmdChangePin:
case CP_cmdGetPinToken:
if (ctap_device_locked())
{
return CTAP2_ERR_PIN_BLOCKED;
}
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
}
if (ret != 0)
{
@@ -1104,7 +1167,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
check_ret(ret);
}
if (num_map)
if (num_map || CP.getRetries)
{
ret = cbor_encoder_close_container(encoder, &map);
check_ret(ret);
@@ -1141,10 +1204,14 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
{
case CTAP_MAKE_CREDENTIAL:
case CTAP_GET_ASSERTION:
case CTAP_CLIENT_PIN:
if (ctap_device_locked())
{
status = CTAP2_ERR_OPERATION_DENIED;
status = CTAP2_ERR_PIN_BLOCKED;
goto done;
}
if (ctap_device_boot_locked())
{
status = CTAP2_ERR_PIN_AUTH_BLOCKED;
goto done;
}
break;
@@ -1153,6 +1220,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
switch(cmd)
{
case CTAP_MAKE_CREDENTIAL:
device_set_status(CTAPHID_STATUS_PROCESSING);
printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n");
t1 = millis();
status = ctap_make_credential(&encoder, pkt_raw, length);
@@ -1164,6 +1232,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
break;
case CTAP_GET_ASSERTION:
device_set_status(CTAPHID_STATUS_PROCESSING);
printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n");
t1 = millis();
status = ctap_get_assertion(&encoder, pkt_raw, length);
@@ -1190,6 +1259,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
case CTAP_CLIENT_PIN:
printf1(TAG_CTAP,"CTAP_CLIENT_PIN\n");
status = ctap_client_pin(&encoder, pkt_raw, length);
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
dump_hex1(TAG_DUMP, buf, cbor_encoder_get_buffer_size(&encoder, buf));
break;
@@ -1228,6 +1298,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
}
done:
device_set_status(CTAPHID_STATUS_IDLE);
getAssertionState.lastcmd = cmd;
if (status != CTAP1_ERR_SUCCESS)
@@ -1235,7 +1306,7 @@ done:
resp->length = 0;
}
printf1(TAG_CTAP,"cbor output structure: %d bytes\n", resp->length);
printf1(TAG_CTAP,"cbor output structure: %d bytes. Return 0x%02x\n", resp->length, status);
return status;
}
@@ -1267,6 +1338,8 @@ void ctap_init()
authenticator_read_state(&STATE);
device_set_status(CTAPHID_STATUS_IDLE);
if (STATE.is_initialized == INITIALIZED_MARKER)
{
printf1(TAG_STOR,"Auth state is initialized\n");
@@ -1295,7 +1368,7 @@ void ctap_init()
{
printf1(TAG_STOR,"pin code: \"%s\"\n", STATE.pin_code);
crypto_sha256_init();
crypto_sha256_update(STATE.pin_code, strnlen(STATE.pin_code, NEW_PIN_ENC_MAX_SIZE));
crypto_sha256_update(STATE.pin_code, STATE.pin_code_length);
crypto_sha256_final(PIN_CODE_HASH);
printf1(TAG_STOR, "attempts_left: %d\n", STATE.remaining_tries);
}
@@ -1335,14 +1408,15 @@ uint8_t ctap_pin_matches(uint8_t * pin, int len)
void ctap_update_pin(uint8_t * pin, int len)
{
// TODO this should go in flash
if (len > NEW_PIN_ENC_MAX_SIZE-1 || len < 4)
if (len > NEW_PIN_ENC_MIN_SIZE || len < 4)
{
printf2(TAG_ERR, "Update pin fail length\n");
exit(1);
}
memset(STATE.pin_code, 0, NEW_PIN_ENC_MAX_SIZE);
memset(STATE.pin_code, 0, NEW_PIN_ENC_MIN_SIZE);
memmove(STATE.pin_code, pin, len);
STATE.pin_code_length = len;
STATE.pin_code[NEW_PIN_ENC_MIN_SIZE - 1] = 0;
crypto_sha256_init();
crypto_sha256_update(STATE.pin_code, len);
@@ -1350,18 +1424,25 @@ void ctap_update_pin(uint8_t * pin, int len)
STATE.is_pin_set = 1;
authenticator_write_state(&STATE, 1);
authenticator_write_state(&STATE, 0);
printf1(TAG_CTAP, "New pin set: %s\n", STATE.pin_code);
}
uint8_t ctap_decrement_pin_attempts()
{
if (STATE.remaining_tries > 0)
if (PIN_BOOT_ATTEMPTS_LEFT > 0)
{
PIN_BOOT_ATTEMPTS_LEFT--;
}
if (! ctap_device_locked())
{
STATE.remaining_tries--;
ctap_flush_state(0);
printf1(TAG_CP, "ATTEMPTS left: %d\n", STATE.remaining_tries);
if (STATE.remaining_tries == 0)
if (ctap_device_locked())
{
memset(PIN_TOKEN,0,sizeof(PIN_TOKEN));
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
@@ -1378,7 +1459,12 @@ uint8_t ctap_decrement_pin_attempts()
int8_t ctap_device_locked()
{
return STATE.remaining_tries == 0;
return STATE.remaining_tries <= 0;
}
int8_t ctap_device_boot_locked()
{
return PIN_BOOT_ATTEMPTS_LEFT <= 0;
}
int8_t ctap_leftover_pin_attempts()
@@ -1389,6 +1475,7 @@ int8_t ctap_leftover_pin_attempts()
void ctap_reset_pin_attempts()
{
STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS;
PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
ctap_flush_state(0);
}

View File

@@ -34,7 +34,8 @@
#define CTAP_VENDOR_FIRST 0x40
#define CTAP_VENDOR_LAST 0xBF
#define CTAP_AAGUID ((uint8_t*)"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")
// AAGUID For Solo
#define CTAP_AAGUID ((uint8_t*)"\x88\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79")
#define MC_clientDataHash 0x01
#define MC_rp 0x02
@@ -126,10 +127,14 @@
#define ALLOW_LIST_MAX_SIZE 20
#define NEW_PIN_ENC_MAX_SIZE 256 // includes NULL terminator
#define NEW_PIN_ENC_MIN_SIZE 64
#define NEW_PIN_MAX_SIZE 64
#define NEW_PIN_MIN_SIZE 4
#define CTAP_RESPONSE_BUFFER_SIZE 1024
#define CTAP_RESPONSE_BUFFER_SIZE 4096
#define PIN_LOCKOUT_ATTEMPTS 8
#define PIN_LOCKOUT_ATTEMPTS 8 // Number of attempts total
#define PIN_BOOT_ATTEMPTS 3 // number of attempts per boot
typedef struct
{
@@ -198,6 +203,7 @@ typedef struct
uint8_t rk;
uint8_t uv;
uint8_t up;
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
@@ -215,6 +221,7 @@ typedef struct
{
uint32_t paramsParsed;
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
uint8_t clientDataHashPresent;
struct rpId rp;
@@ -222,12 +229,14 @@ typedef struct
uint8_t rk;
uint8_t uv;
uint8_t up;
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
int pinProtocol;
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
uint8_t allowListPresent;
} CTAP_getAssertion;
typedef struct
@@ -281,6 +290,7 @@ uint8_t ctap_is_pin_set();
uint8_t ctap_pin_matches(uint8_t * pin, int len);
void ctap_reset();
int8_t ctap_device_locked();
int8_t ctap_device_boot_locked();
// Key storage API

View File

@@ -92,7 +92,7 @@ const char * cbor_value_get_type_string(const CborValue *value)
uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
{
size_t sz, map_length;
uint8_t key[8];
uint8_t key[24];
int ret;
int i;
CborValue map;
@@ -126,6 +126,7 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
printf2(TAG_ERR,"Error, rp map key is too large\n");
return CTAP2_ERR_LIMIT_EXCEEDED;
}
check_ret(ret);
key[sizeof(key) - 1] = 0;
@@ -153,6 +154,11 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
}
else if (strcmp((const char *)key, "name") == 0)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for user.name value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
sz = USER_NAME_LIMIT;
ret = cbor_value_copy_text_string(&map, (char *)MC->user.name, &sz, NULL);
if (ret != CborErrorOutOfMemory)
@@ -161,6 +167,22 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
}
MC->user.name[USER_NAME_LIMIT - 1] = 0;
}
else if (strcmp((const char *)key, "displayName") == 0)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for user.displayName value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
}
else if (strcmp((const char *)key, "icon") == 0)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for user.icon value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
}
else
{
printf1(TAG_PARSE,"ignoring key %s for user map\n", key);
@@ -263,6 +285,19 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
ret = cbor_value_get_array_length(val, &arr_length);
check_ret(ret);
for (i = 0; i < arr_length; i++)
{
if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) != 0)
{
return ret;
}
ret = cbor_value_advance(&arr);
check_ret(ret);
}
ret = cbor_value_enter_container(val,&arr);
check_ret(ret);
for (i = 0; i < arr_length; i++)
{
if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) == 0)
@@ -275,11 +310,6 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
return 0;
}
}
else
{
// Continue? fail?
return ret;
}
ret = cbor_value_advance(&arr);
check_ret(ret);
}
@@ -309,10 +339,40 @@ uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len)
return 0;
}
uint8_t parse_verify_exclude_list(CborValue * val)
{
int i;
int ret;
CborValue arr;
size_t size;
CTAP_credentialDescriptor cred;
if (cbor_value_get_type(val) != CborArrayType)
{
printf2(TAG_ERR,"error, exclude list is not a map\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_get_array_length(val, &size);
check_ret(ret);
ret = cbor_value_enter_container(val,&arr);
check_ret(ret);
for (i = 0; i < size; i++)
{
ret = parse_credential_descriptor(&arr, &cred);
check_ret(ret);
ret = cbor_value_advance(&arr);
check_ret(ret);
}
return 0;
}
uint8_t parse_rp_id(struct rpId * rp, CborValue * val)
{
size_t sz = DOMAIN_NAME_MAX_SIZE;
if (cbor_value_get_type(val) != CborTextStringType)
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
int ret = cbor_value_copy_text_string(val, (char*)rp->id, &sz, NULL);
if (ret == CborErrorOutOfMemory)
{
@@ -413,7 +473,7 @@ uint8_t parse_rp(struct rpId * rp, CborValue * val)
return 0;
}
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv)
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up)
{
size_t sz, map_length;
char key[8];
@@ -463,21 +523,27 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv)
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
if (strcmp(key, "rk") == 0)
if (strncmp(key, "rk",2) == 0)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
*rk = b;
}
else if (strcmp(key, "uv") == 0)
else if (strncmp(key, "uv",2) == 0)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
*uv = b;
}
else if (strncmp(key, "up",2) == 0)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
*up = b;
}
else
{
printf1(TAG_PARSE,"ignoring key %s for option map\n", key);
printf2(TAG_PARSE,"ignoring option specified %s\n", key);
}
@@ -576,27 +642,30 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
break;
case MC_excludeList:
printf1(TAG_MC,"CTAP_excludeList\n");
if( cbor_value_get_type(&map) == CborArrayType )
{
ret = cbor_value_enter_container(&map, &MC->excludeList);
check_ret(ret);
ret = parse_verify_exclude_list(&map);
check_ret(ret);
ret = cbor_value_enter_container(&map, &MC->excludeList);
check_ret(ret);
ret = cbor_value_get_array_length(&map, &MC->excludeListSize);
check_ret(ret);
ret = cbor_value_get_array_length(&map, &MC->excludeListSize);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
printf1(TAG_MC,"CTAP_excludeList done\n");
break;
case MC_extensions:
printf1(TAG_MC,"CTAP_extensions\n");
type = cbor_value_get_type(&map);
if (type != CborMapType)
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case MC_options:
printf1(TAG_MC,"CTAP_options\n");
ret = parse_options(&map, &MC->rk, &MC->uv);
ret = parse_options(&map, &MC->rk, &MC->uv, &MC->up);
check_retr(ret);
break;
case MC_pinAuth:
@@ -661,8 +730,8 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential, &buflen, NULL);
if (buflen != CREDENTIAL_ID_SIZE)
{
printf2(TAG_ERR,"Error, credential is incorrect length\n");
return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail?
printf2(TAG_ERR,"Ignoring credential is incorrect length\n");
//return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail?
}
ret = cbor_value_map_find_value(arr, "type", &val);
@@ -677,13 +746,14 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
buflen = sizeof(type);
cbor_value_copy_text_string(&val, type, &buflen, NULL);
if (strcmp(type, "public-key") == 0)
if (strncmp(type, "public-key",11) == 0)
{
cred->type = PUB_KEY_CRED_PUB_KEY;
}
else
{
cred->type = PUB_KEY_CRED_UNKNOWN;
printf1(TAG_RED, "Unknown type: %s\r\n", type);
}
return 0;
@@ -783,6 +853,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
ret = parse_fixed_byte_string(&map, GA->clientDataHash, CLIENT_DATA_HASH_SIZE);
check_retr(ret);
GA->clientDataHashPresent = 1;
printf1(TAG_GA," "); dump_hex1(TAG_GA, GA->clientDataHash, 32);
break;
@@ -796,10 +867,9 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
case GA_allowList:
printf1(TAG_GA,"GA_allowList\n");
ret = parse_allow_list(GA, &map);
if (ret == 0)
{
check_ret(ret);
GA->allowListPresent = 1;
}
break;
case GA_extensions:
printf1(TAG_GA,"GA_extensions\n");
@@ -807,7 +877,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
case GA_options:
printf1(TAG_GA,"CTAP_options\n");
ret = parse_options(&map, &GA->rk, &GA->uv);
ret = parse_options(&map, &GA->rk, &GA->uv, &GA->up);
check_retr(ret);
break;
case GA_pinAuth:
@@ -1033,10 +1103,11 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length
{
ret = cbor_value_calculate_string_length(&map, &sz);
check_ret(ret);
if (sz > NEW_PIN_ENC_MAX_SIZE)
if (sz > NEW_PIN_ENC_MAX_SIZE || sz < NEW_PIN_ENC_MIN_SIZE)
{
return CTAP1_ERR_OTHER;
return CTAP2_ERR_PIN_POLICY_VIOLATION;
}
CP->newPinEncSize = sz;
sz = NEW_PIN_ENC_MAX_SIZE;
ret = cbor_value_copy_byte_string(&map, CP->newPinEnc, &sz, NULL);
@@ -1078,5 +1149,3 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length
return 0;
}

View File

@@ -42,7 +42,7 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val);
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len);
uint8_t parse_rp_id(struct rpId * rp, CborValue * val);
uint8_t parse_rp(struct rpId * rp, CborValue * val);
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv);
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up);
uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it);
uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int * crv);

View File

@@ -43,6 +43,8 @@ typedef enum
EMPTY = 0,
BUFFERING,
BUFFERED,
HID_ERROR,
HID_IGNORE,
} CTAP_BUFFER_STATE;
@@ -341,7 +343,7 @@ static void send_init_response(uint32_t oldcid, uint32_t newcid, uint8_t * nonce
memmove(init_resp.nonce, nonce, 8);
init_resp.cid = newcid;
init_resp.protocol_version = 0;//?
init_resp.protocol_version = CTAPHID_PROTOCOL_VERSION;
init_resp.version_major = 0;//?
init_resp.version_minor = 0;//?
init_resp.build_version = 0;//?
@@ -367,8 +369,21 @@ void ctaphid_check_timeouts()
}
void ctaphid_update_status(int8_t status)
{
CTAPHID_WRITE_BUFFER wb;
printf1(TAG_HID, "Send device update %d!\n",status);
ctaphid_write_buffer_init(&wb);
void ctaphid_handle_packet(uint8_t * pkt_raw)
wb.cid = buffer_cid();
wb.cmd = CTAPHID_KEEPALIVE;
wb.bcnt = 1;
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, NULL, 0);
}
static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * cid, int * len)
{
CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw);
@@ -378,29 +393,25 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (!is_cont_pkt(pkt)) printf1(TAG_HID, " length: %d\n", ctaphid_packet_len(pkt));
int ret;
uint8_t status;
uint32_t oldcid;
uint32_t newcid;
static CTAPHID_WRITE_BUFFER wb;
uint32_t active_cid;
uint32_t t1,t2;
CTAP_RESPONSE ctap_resp;
*cid = pkt->cid;
if (is_init_pkt(pkt))
{
if (ctaphid_packet_len(pkt) != 8)
{
printf2(TAG_ERR, "Error,invalid length field for init packet\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
*cmd = CTAP1_ERR_INVALID_LENGTH;
return HID_ERROR;
}
if (pkt->cid == 0)
{
printf2(TAG_ERR,"Error, invalid cid 0\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_CHANNEL);
return;
*cmd = CTAP1_ERR_INVALID_CHANNEL;
return HID_ERROR;
}
ctaphid_init();
@@ -426,21 +437,21 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (ret == -1)
{
printf2(TAG_ERR, "Error, not enough memory for new CID. return BUSY.\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
return;
*cmd = CTAP1_ERR_CHANNEL_BUSY;
return HID_ERROR;
}
send_init_response(oldcid, newcid, pkt->pkt.init.payload);
cid_del(newcid);
return;
return HID_IGNORE;
}
else
{
// Check if matches existing CID
if (pkt->cid == CTAPHID_BROADCAST_CID)
{
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_CHANNEL);
return;
*cmd = CTAP1_ERR_INVALID_CHANNEL;
return HID_ERROR;
}
if (cid_exists(pkt->cid))
{
@@ -450,14 +461,14 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
{
printf2(TAG_ERR,"INVALID_SEQ\n");
printf2(TAG_ERR,"Have %d/%d bytes\n", ctap_buffer_offset, ctap_buffer_bcnt);
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ);
return;
*cmd = CTAP1_ERR_INVALID_SEQ;
return HID_ERROR;
}
else if (pkt->cid != buffer_cid())
{
printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid());
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
return;
*cmd = CTAP1_ERR_CHANNEL_BUSY;
return HID_ERROR;
}
}
if (! is_cont_pkt(pkt))
@@ -465,8 +476,8 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (ctaphid_packet_len(pkt) > CTAPHID_BUFFER_SIZE)
{
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
*cmd = CTAP1_ERR_INVALID_LENGTH;
return HID_ERROR;
}
}
else
@@ -474,14 +485,14 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (buffer_status() == EMPTY || pkt->cid != buffer_cid())
{
printf2(TAG_ERR,"ignoring random cont packet\n");
return;
return HID_IGNORE;
}
}
if (buffer_packet(pkt) == SEQUENCE_ERROR)
{
printf2(TAG_ERR,"Buffering sequence error\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ);
return;
*cmd = CTAP1_ERR_INVALID_SEQ;
return HID_ERROR;
}
ret = cid_refresh(pkt->cid);
if (ret != 0)
@@ -489,133 +500,174 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
printf2(TAG_ERR,"Error, refresh cid failed\n");
exit(1);
}
active_cid = pkt->cid;
}
else if (is_cont_pkt(pkt))
{
printf2(TAG_ERR,"ignoring unwarranted cont packet\n");
// Ignore
return;
return HID_IGNORE;
}
else
{
printf2(TAG_ERR,"BUSY\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
return;
*cmd = CTAP1_ERR_CHANNEL_BUSY;
return HID_ERROR;
}
}
switch(buffer_status())
{
case BUFFERING:
printf1(TAG_HID,"BUFFERING\n");
active_cid_timestamp = millis();
break;
case EMPTY:
printf1(TAG_HID,"empty buffer!\n");
case BUFFERED:
switch(buffer_cmd())
{
case CTAPHID_INIT:
printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n");
exit(1);
break;
#ifndef DISABLE_CTAPHID_PING
case CTAPHID_PING:
printf1(TAG_HID,"CTAPHID_PING\n");
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_PING;
wb.bcnt = buffer_len();
t1 = millis();
ctaphid_write(&wb, ctap_buffer, buffer_len());
ctaphid_write(&wb, NULL,0);
t2 = millis();
printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1));
break;
#endif
#ifndef DISABLE_CTAPHID_WINK
case CTAPHID_WINK:
printf1(TAG_HID,"CTAPHID_WINK\n");
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_WINK;
ctaphid_write(&wb,NULL,0);
break;
#endif
#ifndef DISABLE_CTAPHID_CBOR
case CTAPHID_CBOR:
printf1(TAG_HID,"CTAPHID_CBOR\n");
if (buffer_len() == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
}
ctap_response_init(&ctap_resp);
status = ctap_request(ctap_buffer, buffer_len(), &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_CBOR;
wb.bcnt = (ctap_resp.length+1);
t1 = millis();
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
t2 = millis();
printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1));
break;
#endif
case CTAPHID_MSG:
printf1(TAG_HID,"CTAPHID_MSG\n");
if (buffer_len() == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
}
ctap_response_init(&ctap_resp);
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_MSG;
wb.bcnt = (ctap_resp.length);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
break;
default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_COMMAND);
break;
}
cid_del(buffer_cid());
buffer_reset();
break;
default:
printf2(TAG_ERR,"invalid buffer state; abort\n");
exit(1);
break;
}
printf1(TAG_HID,"\n");
*len = buffer_len();
*cmd = buffer_cmd();
return buffer_status();
}
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
{
uint8_t cmd;
uint32_t cid;
int len;
int status;
static uint8_t is_busy = 0;
static CTAPHID_WRITE_BUFFER wb;
CTAP_RESPONSE ctap_resp;
uint32_t t1,t2;
int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len);
if (bufstatus == HID_IGNORE)
{
return 0;
}
if (bufstatus == HID_ERROR)
{
cid_del(cid);
buffer_reset();
ctaphid_send_error(cid, cmd);
return 0;
}
if (bufstatus == BUFFERING)
{
active_cid_timestamp = millis();
return 0;
}
switch(cmd)
{
case CTAPHID_INIT:
printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n");
exit(1);
break;
#ifndef DISABLE_CTAPHID_PING
case CTAPHID_PING:
printf1(TAG_HID,"CTAPHID_PING\n");
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_PING;
wb.bcnt = len;
t1 = millis();
ctaphid_write(&wb, ctap_buffer, len);
ctaphid_write(&wb, NULL,0);
t2 = millis();
printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1));
break;
#endif
#ifndef DISABLE_CTAPHID_WINK
case CTAPHID_WINK:
printf1(TAG_HID,"CTAPHID_WINK\n");
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_WINK;
ctaphid_write(&wb,NULL,0);
break;
#endif
#ifndef DISABLE_CTAPHID_CBOR
case CTAPHID_CBOR:
printf1(TAG_HID,"CTAPHID_CBOR\n");
if (len == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n");
ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH);
return 0;
}
if (is_busy)
{
printf1(TAG_HID,"Channel busy for CBOR\n");
ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY);
return 0;
}
is_busy = 1;
ctap_response_init(&ctap_resp);
status = ctap_request(ctap_buffer, len, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_CBOR;
wb.bcnt = (ctap_resp.length+1);
t1 = millis();
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
t2 = millis();
printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1));
is_busy = 0;
break;
#endif
case CTAPHID_MSG:
printf1(TAG_HID,"CTAPHID_MSG\n");
if (len == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n");
ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH);
return 0;
}
if (is_busy)
{
printf1(TAG_HID,"Channel busy for MSG\n");
ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY);
return 0;
}
is_busy = 1;
ctap_response_init(&ctap_resp);
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_MSG;
wb.bcnt = (ctap_resp.length);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
case CTAPHID_CANCEL:
printf1(TAG_HID,"CTAPHID_CANCEL\n");
is_busy = 0;
break;
default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
break;
}
cid_del(cid);
buffer_reset();
printf1(TAG_HID,"\n");
if (!is_busy) return cmd;
else return 0;
}

View File

@@ -36,6 +36,7 @@
#define CTAPHID_CBOR (TYPE_INIT | 0x10)
#define CTAPHID_CANCEL (TYPE_INIT | 0x11)
#define CTAPHID_ERROR (TYPE_INIT | 0x3f)
#define CTAPHID_KEEPALIVE (TYPE_INIT | 0x3b)
#define ERR_INVALID_CMD 0x01
#define ERR_INVALID_PAR 0x02
@@ -43,6 +44,11 @@
#define ERR_MSG_TIMEOUT 0x05
#define ERR_CHANNEL_BUSY 0x06
#define CTAPHID_PROTOCOL_VERSION 2
#define CTAPHID_STATUS_IDLE 0
#define CTAPHID_STATUS_PROCESSING 1
#define CTAPHID_STATUS_UPNEEDED 2
#define CTAPHID_INIT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-7)
#define CTAPHID_CONT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-5)
@@ -91,10 +97,12 @@ typedef struct
void ctaphid_init();
void ctaphid_handle_packet(uint8_t * pkt_raw);
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw);
void ctaphid_check_timeouts();
void ctaphid_update_status(int8_t status);
#define ctaphid_packet_len(pkt) ((uint16_t)((pkt)->pkt.init.bcnth << 8) | ((pkt)->pkt.init.bcntl))

View File

@@ -56,8 +56,12 @@ void authenticator_write_state(AuthenticatorState *, int backup);
// Called each main loop. Doesn't need to do anything.
void device_manage();
// sets status that's uses for sending status updates ~100ms.
// A timer should be set up to call `ctaphid_update_status`
void device_set_status(int status);
// Test for user presence
// Return 1 for user is present, 0 user not present
// Return 1 for user is present, 0 user not present, -1 if cancel is requested.
extern int ctap_user_presence_test();
// Generate @num bytes of random numbers to @dest

View File

@@ -45,20 +45,20 @@ int main(int argc, char * argv[])
set_logging_mask(
/*0*/
TAG_GEN|
/*TAG_MC |*/
/*TAG_GA |*/
TAG_WALLET |
// TAG_GEN|
// TAG_MC |
// TAG_GA |
// TAG_WALLET |
TAG_STOR |
/*TAG_CP |*/
// TAG_CP |
TAG_CTAP|
// TAG_HID|
// TAG_HID|
/*TAG_U2F|*/
/*TAG_PARSE |*/
// TAG_TIME|
/*TAG_DUMP|*/
/*TAG_GREEN|*/
/*TAG_RED|*/
// TAG_PARSE |
//TAG_TIME|
// TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_ERR
);
@@ -89,12 +89,11 @@ int main(int argc, char * argv[])
if (usbhid_recv(hidmsg) > 0)
{
printf1(TAG_DUMP,"%d>> ",count++); dump_hex1(TAG_DUMP, hidmsg,sizeof(hidmsg));
t2 = millis();
ctaphid_handle_packet(hidmsg);
accum += millis() - t2;
printf1(TAG_TIME,"accum: %d\n", (uint32_t)accum);
printf1(TAG_TIME,"dt: %d\n", t2 - dt);
// printf1(TAG_TIME,"accum: %d\n", (uint32_t)accum);
// printf1(TAG_TIME,"dt: %d\n", t2 - dt);
dt = t2;
memset(hidmsg, 0, sizeof(hidmsg));
}

View File

@@ -39,8 +39,9 @@ typedef struct
// Pin information
uint8_t is_initialized;
uint8_t is_pin_set;
uint8_t pin_code[NEW_PIN_ENC_MAX_SIZE];
uint8_t remaining_tries;
uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE];
int pin_code_length;
int8_t remaining_tries;
uint16_t key_lens[MAX_KEYS];
uint8_t key_space[KEY_SPACE_BYTES];