From 4b35a37613207bcd3ccdbc71a10e3c2460489a51 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 15 May 2018 23:53:41 -0400 Subject: [PATCH] start on clientPin --- ctap.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- ctap.h | 33 +++++++--- 2 files changed, 201 insertions(+), 23 deletions(-) diff --git a/ctap.c b/ctap.c index 62bcffb..e3ba038 100644 --- a/ctap.c +++ b/ctap.c @@ -16,6 +16,9 @@ #define check_ret(r) _check_ret(r,__LINE__, __FILE__);\ 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 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"; } +/*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) { int ret; CborEncoder array; CborEncoder map; CborEncoder options; + CborEncoder pins; 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); { @@ -91,22 +127,46 @@ uint8_t ctap_get_info(CborEncoder * encoder) { ret = cbor_encoder_create_array(&map, &array, number_of_versions); check_ret(ret); - ret = cbor_encode_text_stringz(&array, "U2F_V2"); - check_ret(ret); - ret = cbor_encode_text_stringz(&array, "FIDO_2_0"); - check_ret(ret); + { + ret = cbor_encode_text_stringz(&array, "U2F_V2"); + check_ret(ret); + ret = cbor_encode_text_stringz(&array, "FIDO_2_0"); + check_ret(ret); + } ret = cbor_encoder_close_container(&map, &array); check_ret(ret); } - ret = cbor_encode_uint(&map, RESP_aaguid); // aaguid key + ret = cbor_encode_uint(&map, RESP_aaguid); check_ret(ret); { ret = cbor_encode_byte_string(&map, CTAP_AAGUID, 16); 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); { 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); 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) @@ -1233,6 +1389,7 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) uint8_t status = 0; uint8_t cmd = *pkt_raw; pkt_raw++; + length--; 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); _ENCODER = &encoder; - printf1("cbor req: "); dump_hex(pkt_raw, length - 1); + printf1("cbor req: "); dump_hex(pkt_raw, length); switch(cmd) { case CTAP_MAKE_CREDENTIAL: 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)); @@ -1260,7 +1417,7 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) break; case CTAP_GET_ASSERTION: 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); @@ -1274,14 +1431,14 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) printf1("CTAP_GET_INFO\n"); status = ctap_get_info(&encoder); - dump_hex(buf, 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; case CTAP_CLIENT_PIN: printf1("CTAP_CLIENT_PIN\n"); + status = ctap_client_pin(&encoder, pkt_raw, length); break; case CTAP_RESET: 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; } - 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); return status; } +void ctap_init() +{ + if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1) + { + printf2("Error, rng failed\n"); + exit(1); + } +} diff --git a/ctap.h b/ctap.h index 817f3b5..d4eec1f 100644 --- a/ctap.h +++ b/ctap.h @@ -79,6 +79,7 @@ #define RP_NAME_LIMIT 32 // application limit, name parameter isn't needed. #define USER_ID_MAX_SIZE 64 #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_COUNTER_SIZE (4) @@ -92,6 +93,8 @@ #define ALLOW_LIST_MAX_SIZE 20 +#define NEW_PIN_ENC_MAX_SIZE 256 + typedef struct { uint8_t id[USER_ID_MAX_SIZE]; @@ -167,25 +170,35 @@ typedef struct CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE]; 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; +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); +// Run ctap related power-up procedures (init pinToken, generate shared secret) +void ctap_init(); + // Test for user presence // Return 1 for user is present, 0 user not present extern int ctap_user_presence_test(); // 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); // Increment atomic counter and return it.