start on clientPin

This commit is contained in:
Conor Patrick
2018-05-15 23:53:41 -04:00
parent dd5965f8ac
commit 4b35a37613
2 changed files with 201 additions and 23 deletions

191
ctap.c
View File

@@ -16,6 +16,9 @@
#define check_ret(r) _check_ret(r,__LINE__, __FILE__);\ #define check_ret(r) _check_ret(r,__LINE__, __FILE__);\
if ((r) != CborNoError) return CTAP2_ERR_CBOR_PARSING; if ((r) != CborNoError) return CTAP2_ERR_CBOR_PARSING;
#define PIN_TOKEN_SIZE 16
static uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
static CborEncoder * _ENCODER; static CborEncoder * _ENCODER;
static void _check_ret(CborError ret, int line, const char * filename) static void _check_ret(CborError ret, int line, const char * filename)
{ {
@@ -73,16 +76,49 @@ static const char * cbor_value_get_type_string(const CborValue *value)
return "Invalid type"; return "Invalid type";
} }
/*static CborError cbor_value_map_find_value_by_int(const CborValue *map, const int key, CborValue * element)*/
/*{*/
/*size_t sz;*/
/*CborValue ckey, it;*/
/*int rkey;*/
/*int ret = cbor_value_get_map_length(map, &sz);*/
/*check_ret(ret);*/
/*cbor_value_enter_container(map, &it);*/
/*int i;*/
/*for (i = 0; i < sz; i++)*/
/*{*/
/*if (cbor_value_get_type(&it) == CborIntegerType)*/
/*{*/
/*ret = cbor_value_advance(&it);*/
/*check_ret(ret);*/
/*ret = cbor_value_get_int_checked(&it, &rkey);*/
/*check_ret(ret);*/
/*ret = cbor_value_advance(&it);*/
/*check_ret(ret);*/
/*}*/
/*else*/
/*{*/
/*cbor_value_advance(&it);*/
/*cbor_value_advance(&it);*/
/*}*/
/*}*/
/*return CborNoError;*/
/*}*/
uint8_t ctap_get_info(CborEncoder * encoder) uint8_t ctap_get_info(CborEncoder * encoder)
{ {
int ret; int ret;
CborEncoder array; CborEncoder array;
CborEncoder map; CborEncoder map;
CborEncoder options; CborEncoder options;
CborEncoder pins;
const int number_of_versions = 2; const int number_of_versions = 2;
ret = cbor_encoder_create_map(encoder, &map, 3); ret = cbor_encoder_create_map(encoder, &map, 5);
check_ret(ret); check_ret(ret);
{ {
@@ -91,22 +127,46 @@ uint8_t ctap_get_info(CborEncoder * encoder)
{ {
ret = cbor_encoder_create_array(&map, &array, number_of_versions); ret = cbor_encoder_create_array(&map, &array, number_of_versions);
check_ret(ret); check_ret(ret);
ret = cbor_encode_text_stringz(&array, "U2F_V2"); {
check_ret(ret); ret = cbor_encode_text_stringz(&array, "U2F_V2");
ret = cbor_encode_text_stringz(&array, "FIDO_2_0"); check_ret(ret);
check_ret(ret); ret = cbor_encode_text_stringz(&array, "FIDO_2_0");
check_ret(ret);
}
ret = cbor_encoder_close_container(&map, &array); ret = cbor_encoder_close_container(&map, &array);
check_ret(ret); check_ret(ret);
} }
ret = cbor_encode_uint(&map, RESP_aaguid); // aaguid key ret = cbor_encode_uint(&map, RESP_aaguid);
check_ret(ret); check_ret(ret);
{ {
ret = cbor_encode_byte_string(&map, CTAP_AAGUID, 16); ret = cbor_encode_byte_string(&map, CTAP_AAGUID, 16);
check_ret(ret); check_ret(ret);
} }
ret = cbor_encode_uint(&map, RESP_options); // aaguid key ret = cbor_encode_uint(&map, RESP_maxMsgSize);
check_ret(ret);
{
ret = cbor_encode_int(&map, CTAP_MAX_MESSAGE_SIZE);
check_ret(ret);
}
ret = cbor_encode_uint(&map, RESP_pinProtocols);
check_ret(ret);
{
ret = cbor_encoder_create_array(&map, &pins, 1);
check_ret(ret);
{
ret = cbor_encode_int(&pins, 1);
check_ret(ret);
}
ret = cbor_encoder_close_container(&map, &pins);
check_ret(ret);
}
ret = cbor_encode_uint(&map, RESP_options);
check_ret(ret); check_ret(ret);
{ {
ret = cbor_encoder_create_map(&map, &options,4); ret = cbor_encoder_create_map(&map, &options,4);
@@ -1224,8 +1284,104 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
ret = cbor_encoder_close_container(encoder, &map); ret = cbor_encoder_close_container(encoder, &map);
check_ret(ret); check_ret(ret);
}
int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
{
int ret;
int i,j;
int key;
size_t map_length;
size_t sz;
CborParser parser;
CborValue it,map;
memset(CP, 0, sizeof(CTAP_clientPin));
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
check_ret(ret);
CborType type = cbor_value_get_type(&it);
if (type != CborMapType)
{
printf2("Error, expecting cbor map\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_enter_container(&it,&map);
check_ret(ret);
ret = cbor_value_get_map_length(&it, &map_length);
check_ret(ret);
printf1("CP map has %d elements\n",map_length);
for (i = 0; i < map_length; i++)
{
type = cbor_value_get_type(&map);
if (type != CborIntegerType)
{
printf2("Error, expecting int for map key\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_get_int_checked(&map, &key);
check_ret(ret);
ret = cbor_value_advance(&map);
check_ret(ret);
ret = 0;
switch(key)
{
case CP_pinProtocol:
printf("CP_pinProtocol\n");
break;
case CP_subCommand:
printf("CP_subCommand\n");
break;
case CP_keyAgreement:
printf("CP_keyAgreement\n");
break;
case CP_pinAuth:
printf("CP_pinAuth\n");
break;
case CP_newPinEnc:
printf("CP_newPinEnc\n");
break;
case CP_pinHashEnc:
printf("CP_pinHashEnc\n");
break;
case CP_getKeyAgreement:
printf("CP_getKeyAgreement\n");
break;
case CP_getRetries:
printf("CP_getRetries\n");
break;
default:
printf1("Unknown key %d\n", key);
}
ret = cbor_value_advance(&map);
check_ret(ret);
}
return 0;
}
uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
{
CTAP_clientPin CP;
int ret = ctap_parse_client_pin(&CP,request,length);
if (ret != 0)
{
printf2("error, parse_client_pin failed\n");
return ret;
}
return 0;
} }
uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
@@ -1233,6 +1389,7 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
uint8_t status = 0; uint8_t status = 0;
uint8_t cmd = *pkt_raw; uint8_t cmd = *pkt_raw;
pkt_raw++; pkt_raw++;
length--;
static uint8_t buf[1024]; static uint8_t buf[1024];
@@ -1245,14 +1402,14 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
cbor_encoder_init(&encoder, buf, sizeof(buf), 0); cbor_encoder_init(&encoder, buf, sizeof(buf), 0);
_ENCODER = &encoder; _ENCODER = &encoder;
printf1("cbor req: "); dump_hex(pkt_raw, length - 1); printf1("cbor req: "); dump_hex(pkt_raw, length);
switch(cmd) switch(cmd)
{ {
case CTAP_MAKE_CREDENTIAL: case CTAP_MAKE_CREDENTIAL:
printf1("CTAP_MAKE_CREDENTIAL\n"); printf1("CTAP_MAKE_CREDENTIAL\n");
status = ctap_make_credential(&encoder, pkt_raw, length - 1); status = ctap_make_credential(&encoder, pkt_raw, length);
dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf)); dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf));
@@ -1260,7 +1417,7 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
break; break;
case CTAP_GET_ASSERTION: case CTAP_GET_ASSERTION:
printf1("CTAP_GET_ASSERTION\n"); printf1("CTAP_GET_ASSERTION\n");
status = ctap_get_assertion(&encoder, pkt_raw, length - 1); status = ctap_get_assertion(&encoder, pkt_raw, length);
resp->length = cbor_encoder_get_buffer_size(&encoder, buf); resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
@@ -1274,14 +1431,14 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
printf1("CTAP_GET_INFO\n"); printf1("CTAP_GET_INFO\n");
status = ctap_get_info(&encoder); status = ctap_get_info(&encoder);
dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf));
resp->length = cbor_encoder_get_buffer_size(&encoder, buf); resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf));
break; break;
case CTAP_CLIENT_PIN: case CTAP_CLIENT_PIN:
printf1("CTAP_CLIENT_PIN\n"); printf1("CTAP_CLIENT_PIN\n");
status = ctap_client_pin(&encoder, pkt_raw, length);
break; break;
case CTAP_RESET: case CTAP_RESET:
printf1("CTAP_RESET\n"); printf1("CTAP_RESET\n");
@@ -1299,9 +1456,17 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
resp->length = 0; resp->length = 0;
} }
printf1("cbor input structure: %d bytes\n", length - 1); printf1("cbor input structure: %d bytes\n", length);
printf1("cbor output structure: %d bytes\n", resp->length); printf1("cbor output structure: %d bytes\n", resp->length);
return status; return status;
} }
void ctap_init()
{
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
{
printf2("Error, rng failed\n");
exit(1);
}
}

33
ctap.h
View File

@@ -79,6 +79,7 @@
#define RP_NAME_LIMIT 32 // application limit, name parameter isn't needed. #define RP_NAME_LIMIT 32 // application limit, name parameter isn't needed.
#define USER_ID_MAX_SIZE 64 #define USER_ID_MAX_SIZE 64
#define USER_NAME_LIMIT 65 // Must be minimum of 64 bytes but can be more. #define USER_NAME_LIMIT 65 // Must be minimum of 64 bytes but can be more.
#define CTAP_MAX_MESSAGE_SIZE 1024
#define CREDENTIAL_TAG_SIZE 16 #define CREDENTIAL_TAG_SIZE 16
#define CREDENTIAL_COUNTER_SIZE (4) #define CREDENTIAL_COUNTER_SIZE (4)
@@ -92,6 +93,8 @@
#define ALLOW_LIST_MAX_SIZE 20 #define ALLOW_LIST_MAX_SIZE 20
#define NEW_PIN_ENC_MAX_SIZE 256
typedef struct typedef struct
{ {
uint8_t id[USER_ID_MAX_SIZE]; uint8_t id[USER_ID_MAX_SIZE];
@@ -167,25 +170,35 @@ typedef struct
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE]; CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
int credLen; int credLen;
//uint8_t userId[USER_ID_MAX_SIZE];
//uint8_t userIdSize;
//uint8_t userName[USER_NAME_LIMIT];
//uint8_t publicKeyCredentialType;
//int32_t COSEAlgorithmIdentifier;
//uint8_t pinProtocol;
} CTAP_getAssertion; } CTAP_getAssertion;
typedef struct
{
int pinProtocol;
int subCommand;
struct
{
} keyAgreement;
uint8_t pinAuth[16];
uint8_t newPinEnc[NEW_PIN_ENC_MAX_SIZE];
uint8_t pinHashEnc[16];
int getKeyAgreement;
int getRetries;
} CTAP_clientPin;
uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp); uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp);
// Run ctap related power-up procedures (init pinToken, generate shared secret)
void ctap_init();
// Test for user presence // Test for user presence
// Return 1 for user is present, 0 user not present // Return 1 for user is present, 0 user not present
extern int ctap_user_presence_test(); extern int ctap_user_presence_test();
// Generate @num bytes of random numbers to @dest // Generate @num bytes of random numbers to @dest
// return 1 if success, error otherwise
extern int ctap_generate_rng(uint8_t * dst, size_t num); extern int ctap_generate_rng(uint8_t * dst, size_t num);
// Increment atomic counter and return it. // Increment atomic counter and return it.