From 4dd6eea8e031a42e5a1f84fc36063af147d9a9aa Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 14 May 2018 22:55:47 -0400 Subject: [PATCH] properly propogate errors --- ctap.c | 315 +++++++++++++++++++++++++++----------------------- ctap_errors.h | 51 ++++++++ ctaphid.c | 4 +- log.c | 14 +++ log.h | 23 ++++ 5 files changed, 262 insertions(+), 145 deletions(-) create mode 100644 ctap_errors.h create mode 100644 log.c create mode 100644 log.h diff --git a/ctap.c b/ctap.c index 64c3cab..62bcffb 100644 --- a/ctap.c +++ b/ctap.c @@ -6,21 +6,23 @@ #include "cbor.h" #include "ctap.h" +#include "ctap_errors.h" #include "cose_key.h" #include "crypto.h" #include "util.h" +#include "log.h" -#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; + static CborEncoder * _ENCODER; static void _check_ret(CborError ret, int line, const char * filename) { if (ret != CborNoError) { - printf("CborError: 0x%x: %s: %d: %s\n", ret, filename, line, cbor_error_string(ret)); - if (ret == 0x80000000) - printf(" need %d more bytes\n",cbor_encoder_get_extra_bytes_needed(_ENCODER)); - exit(1); + printf1("CborError: 0x%x: %s: %d: %s\n", ret, filename, line, cbor_error_string(ret)); + /*exit(1);*/ } } @@ -71,7 +73,7 @@ static const char * cbor_value_get_type_string(const CborValue *value) return "Invalid type"; } -void ctap_get_info(CborEncoder * encoder) +uint8_t ctap_get_info(CborEncoder * encoder) { int ret; CborEncoder array; @@ -147,23 +149,25 @@ void ctap_get_info(CborEncoder * encoder) } ret = cbor_encoder_close_container(encoder, &map); check_ret(ret); + + return CTAP1_ERR_SUCCESS; } -static int parse_client_data_hash(uint8_t * clientDataHash, CborValue * val) +static uint8_t parse_client_data_hash(uint8_t * clientDataHash, CborValue * val) { size_t sz; int ret; if (cbor_value_get_type(val) != CborByteStringType) { - printf("error, wrong type\n"); - return -1; + printf2("error, wrong type\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_calculate_string_length(val, &sz); check_ret(ret); if (sz != CLIENT_DATA_HASH_SIZE) { - printf("error, wrong size for client data hash\n"); - return -1; + printf2("error, wrong size for client data hash\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_copy_byte_string(val, clientDataHash, &sz, NULL); check_ret(ret); @@ -172,7 +176,7 @@ static int parse_client_data_hash(uint8_t * clientDataHash, CborValue * val) } -static int parse_user(CTAP_makeCredential * MC, CborValue * val) +static uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val) { size_t sz, map_length; uint8_t key[8]; @@ -183,8 +187,8 @@ static int parse_user(CTAP_makeCredential * MC, CborValue * val) if (cbor_value_get_type(val) != CborMapType) { - printf("error, wrong type\n"); - return -1; + printf2("error, wrong type\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_enter_container(val,&map); @@ -197,8 +201,8 @@ static int parse_user(CTAP_makeCredential * MC, CborValue * val) { if (cbor_value_get_type(&map) != CborTextStringType) { - printf("Error, expecting text string type for user map key, got %s\n", cbor_value_get_type_string(&map)); - return -1; + printf2("Error, expecting text string type for user map key, got %s\n", cbor_value_get_type_string(&map)); + return CTAP2_ERR_INVALID_CBOR_TYPE; } sz = sizeof(key); @@ -206,8 +210,8 @@ static int parse_user(CTAP_makeCredential * MC, CborValue * val) if (ret == CborErrorOutOfMemory) { - printf("Error, rp map key is too large\n"); - return -1; + printf2("Error, rp map key is too large\n"); + return CTAP2_ERR_LIMIT_EXCEEDED; } check_ret(ret); key[sizeof(key) - 1] = 0; @@ -220,16 +224,16 @@ static int parse_user(CTAP_makeCredential * MC, CborValue * val) if (cbor_value_get_type(&map) != CborByteStringType) { - printf("Error, expecting byte string type for rp map value\n"); - return -1; + printf2("Error, expecting byte string type for rp map value\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } sz = USER_ID_MAX_SIZE; ret = cbor_value_copy_byte_string(&map, MC->user.id, &sz, NULL); if (ret == CborErrorOutOfMemory) { - printf("Error, USER_ID is too large\n"); - return -1; + printf2("Error, USER_ID is too large\n"); + return CTAP2_ERR_LIMIT_EXCEEDED; } MC->user.id_size = sz; check_ret(ret); @@ -246,7 +250,7 @@ static int parse_user(CTAP_makeCredential * MC, CborValue * val) } else { - printf("ignoring key %s for user map\n", key); + printf1("ignoring key %s for user map\n", key); } ret = cbor_value_advance(&map); @@ -270,8 +274,8 @@ static int parse_pub_key_cred_param(CborValue * val, uint8_t * cred_type, int32_ if (cbor_value_get_type(val) != CborMapType) { - printf("error, expecting map type\n"); - return -1; + printf2("error, expecting map type, got %s\n", cbor_value_get_type_string(val)); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_map_find_value(val, "type", &cred); @@ -281,13 +285,13 @@ static int parse_pub_key_cred_param(CborValue * val, uint8_t * cred_type, int32_ if (cbor_value_get_type(&cred) != CborTextStringType) { - printf("Error, parse_pub_key could not find credential param\n"); - return -1; + printf2("Error, parse_pub_key could not find credential param\n"); + return CTAP2_ERR_MISSING_PARAMETER; } if (cbor_value_get_type(&alg) != CborIntegerType) { - printf("Error, parse_pub_key could not find alg param\n"); - return -1; + printf2("Error, parse_pub_key could not find alg param\n"); + return CTAP2_ERR_MISSING_PARAMETER; } ret = cbor_value_copy_text_string(&cred, type_str, &sz, NULL); @@ -324,7 +328,7 @@ static int pub_key_cred_param_supported(uint8_t cred, int32_t alg) return CREDENTIAL_NOT_SUPPORTED; } -static int parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) +static uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) { size_t sz, arr_length; uint8_t cred_type; @@ -337,8 +341,8 @@ static int parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) if (cbor_value_get_type(val) != CborArrayType) { - printf("error, expecting array type\n"); - return -1; + printf2("error, expecting array type\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_enter_container(val,&arr); @@ -349,7 +353,7 @@ static int parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) for (i = 0; i < arr_length; i++) { - if (parse_pub_key_cred_param(&arr, &cred_type, &alg_type) == 0) + if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) == 0) { if (pub_key_cred_param_supported(cred_type, alg_type) == CREDENTIAL_IS_SUPPORTED) { @@ -362,13 +366,14 @@ static int parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val) else { // Continue? fail? + return ret; } ret = cbor_value_advance(&arr); check_ret(ret); } - printf("Error, no public key credential parameters are supported!\n"); - return -1; + printf2("Error, no public key credential parameters are supported!\n"); + return CTAP2_ERR_UNSUPPORTED_ALGORITHM; } @@ -378,8 +383,8 @@ static int parse_rp_id(struct rpId * rp, CborValue * val) int ret = cbor_value_copy_text_string(val, rp->id, &sz, NULL); if (ret == CborErrorOutOfMemory) { - printf("Error, RP_ID is too large\n"); - return -1; + printf2("Error, RP_ID is too large\n"); + return CTAP2_ERR_LIMIT_EXCEEDED; } rp->id[DOMAIN_NAME_MAX_SIZE] = 0; // Extra byte defined in struct. rp->size = sz; @@ -387,7 +392,7 @@ static int parse_rp_id(struct rpId * rp, CborValue * val) return 0; } -static int parse_rp(struct rpId * rp, CborValue * val) +static uint8_t parse_rp(struct rpId * rp, CborValue * val) { size_t sz, map_length; uint8_t key[8]; @@ -398,8 +403,8 @@ static int parse_rp(struct rpId * rp, CborValue * val) if (cbor_value_get_type(val) != CborMapType) { - printf("error, wrong type\n"); - return -1; + printf2("error, wrong type\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_enter_container(val,&map); @@ -414,8 +419,8 @@ static int parse_rp(struct rpId * rp, CborValue * val) { if (cbor_value_get_type(&map) != CborTextStringType) { - printf("Error, expecting text string type for rp map key, got %s\n", cbor_value_get_type_string(&map)); - return -1; + printf2("Error, expecting text string type for rp map key, got %s\n", cbor_value_get_type_string(&map)); + return CTAP2_ERR_INVALID_CBOR_TYPE; } sz = sizeof(key); @@ -423,8 +428,8 @@ static int parse_rp(struct rpId * rp, CborValue * val) if (ret == CborErrorOutOfMemory) { - printf("Error, rp map key is too large\n"); - return -1; + printf2("Error, rp map key is too large\n"); + return CTAP2_ERR_LIMIT_EXCEEDED; } check_ret(ret); key[sizeof(key) - 1] = 0; @@ -434,8 +439,8 @@ static int parse_rp(struct rpId * rp, CborValue * val) if (cbor_value_get_type(&map) != CborTextStringType) { - printf("Error, expecting text string type for rp map value\n"); - return -1; + printf2("Error, expecting text string type for rp map value\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } if (strcmp(key, "id") == 0) @@ -458,7 +463,7 @@ static int parse_rp(struct rpId * rp, CborValue * val) } else { - printf("ignoring key %s for RP map\n", key); + printf1("ignoring key %s for RP map\n", key); } ret = cbor_value_advance(&map); @@ -467,8 +472,8 @@ static int parse_rp(struct rpId * rp, CborValue * val) } if (rp->size == 0) { - printf("Error, no RPID provided\n"); - return -1; + printf2("Error, no RPID provided\n"); + return CTAP2_ERR_MISSING_PARAMETER; } @@ -476,7 +481,7 @@ static int parse_rp(struct rpId * rp, CborValue * val) } -static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length) +static uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length) { int ret; int i; @@ -493,8 +498,8 @@ static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * en CborType type = cbor_value_get_type(&it); if (type != CborMapType) { - printf("Error, expecting cbor map\n"); - return -1; + printf2("Error, expecting cbor map\n"); + return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; } ret = cbor_value_enter_container(&it,&map); @@ -503,14 +508,15 @@ static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * en ret = cbor_value_get_map_length(&it, &map_length); check_ret(ret); - printf("map has %d elements\n",map_length); + printf1("map has %d elements\n",map_length); for (i = 0; i < map_length; i++) { type = cbor_value_get_type(&map); if (type != CborIntegerType) { - printf("Error, expecting int for map key\n"); + printf2("Error, expecting int for map key\n"); + return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; } ret = cbor_value_get_int_checked(&map, &key); check_ret(ret); @@ -523,7 +529,7 @@ static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * en { case MC_clientDataHash: - printf("CTAP_clientDataHash\n"); + printf1("CTAP_clientDataHash\n"); ret = parse_client_data_hash(MC->clientDataHash, &map); if (ret == 0) @@ -531,10 +537,10 @@ static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * en MC->paramsParsed |= PARAM_clientDataHash; } - printf(" "); dump_hex(MC->clientDataHash, 32); + printf1(" "); dump_hex(MC->clientDataHash, 32); break; case MC_rp: - printf("CTAP_rp\n"); + printf1("CTAP_rp\n"); ret = parse_rp(&MC->rp, &map); if (ret == 0) @@ -543,44 +549,44 @@ static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * en } - printf(" ID: %s\n", MC->rp.id); - printf(" name: %s\n", MC->rp.name); + printf1(" ID: %s\n", MC->rp.id); + printf1(" name: %s\n", MC->rp.name); break; case MC_user: - printf("CTAP_user\n"); + printf1("CTAP_user\n"); ret = parse_user(MC, &map); - printf(" ID: "); dump_hex(MC->user.id, MC->user.id_size); - printf(" name: %s\n", MC->user.name); + printf1(" ID: "); dump_hex(MC->user.id, MC->user.id_size); + printf1(" name: %s\n", MC->user.name); break; case MC_pubKeyCredParams: - printf("CTAP_pubKeyCredParams\n"); + printf1("CTAP_pubKeyCredParams\n"); ret = parse_pub_key_cred_params(MC, &map); - printf(" cred_type: 0x%02x\n", MC->publicKeyCredentialType); - printf(" alg_type: %d\n", MC->COSEAlgorithmIdentifier); + printf1(" cred_type: 0x%02x\n", MC->publicKeyCredentialType); + printf1(" alg_type: %d\n", MC->COSEAlgorithmIdentifier); break; case MC_excludeList: - printf("CTAP_excludeList\n"); + printf1("CTAP_excludeList\n"); break; case MC_extensions: - printf("CTAP_extensions\n"); + printf1("CTAP_extensions\n"); break; case MC_options: - printf("CTAP_options\n"); + printf1("CTAP_options\n"); break; case MC_pinAuth: - printf("CTAP_pinAuth\n"); + printf1("CTAP_pinAuth\n"); break; case MC_pinProtocol: - printf("CTAP_pinProtocol\n"); + printf1("CTAP_pinProtocol\n"); break; default: - printf("invalid key %d\n", key); + printf1("invalid key %d\n", key); } if (ret != 0) @@ -603,12 +609,12 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input, ret = cbor_encoder_create_map(cose_key, &map, 5); int extra = cbor_encoder_get_extra_bytes_needed(&map); - printf(" extra? %d\n", extra); + printf1(" extra? %d\n", extra); check_ret(ret); if (credtype != PUB_KEY_CRED_PUB_KEY) { - printf("Error, pubkey credential type not supported\n"); + printf2("Error, pubkey credential type not supported\n"); return -1; } switch(algtype) @@ -618,7 +624,7 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input, crypto_ecc256_derive_public_key(hmac_input, len, x, y); break; default: - printf("Error, COSE alg %d not supported\n", algtype); + printf2("Error, COSE alg %d not supported\n", algtype); return -1; } @@ -687,7 +693,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au if((sizeof(CTAP_authData) - sizeof(CTAP_attestHeader)) > len) { - printf("assertion fail, auth_data_buf must be at least %d bytes\n", sizeof(CTAP_authData) - sizeof(CTAP_attestHeader)); + printf1("assertion fail, auth_data_buf must be at least %d bytes\n", sizeof(CTAP_authData) - sizeof(CTAP_attestHeader)); exit(1); } @@ -727,7 +733,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au ctap_generate_cose_key(&cose_key, authData->attest.credential.id, CREDENTIAL_ID_SIZE, credtype, algtype); - printf("COSE_KEY: "); dump_hex(cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf)); + printf1("COSE_KEY: "); dump_hex(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 @@ -766,9 +772,9 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa crypto_ecc256_sign(hashbuf, 32, sigbuf); - /*printf("signature hash: "); dump_hex(hashbuf, 32);*/ - /*printf("R: "); dump_hex(sigbuf, 32);*/ - /*printf("S: "); dump_hex(sigbuf+32, 32);*/ + /*printf1("signature hash: "); dump_hex(hashbuf, 32);*/ + /*printf1("R: "); dump_hex(sigbuf, 32);*/ + /*printf1("S: "); dump_hex(sigbuf+32, 32);*/ // Need to caress into dumb der format .. uint8_t pad_s = (sigbuf[32] & 0x80) == 0x80; @@ -790,7 +796,7 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa return 0x46 + pad_s + pad_r; } -void ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len) +uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len) { int ret; @@ -832,7 +838,7 @@ void ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len) } -void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) +uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) { CTAP_makeCredential MC; int ret; @@ -844,13 +850,13 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) ret = ctap_parse_make_credential(&MC,encoder,request,length); if (ret != 0) { - printf("error, parse_make_credential failed\n"); - return; + printf2("error, parse_make_credential failed\n"); + return ret; } if ((MC.paramsParsed & MC_requiredMask) != MC_requiredMask) { - printf("error, required parameter(s) for makeCredential are missing\n"); - return; + printf2("error, required parameter(s) for makeCredential are missing\n"); + return CTAP2_ERR_MISSING_PARAMETER; } @@ -864,9 +870,10 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) crypto_ecc256_load_attestation_key(); int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder); - printf("der sig [%d]: ", sigder_sz); dump_hex(sigder, sigder_sz); + printf1("der sig [%d]: ", sigder_sz); dump_hex(sigder, sigder_sz); - ctap_add_attest_statement(&map, sigder, sigder_sz); + ret = ctap_add_attest_statement(&map, sigder, sigder_sz); + check_ret(ret); { ret = cbor_encode_int(&map,RESP_fmt); @@ -877,6 +884,7 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) ret = cbor_encoder_close_container(encoder, &map); check_ret(ret); + return CTAP1_ERR_SUCCESS; } static int parse_allow_list(CTAP_getAssertion * GA, CborValue * it) @@ -888,8 +896,8 @@ static int parse_allow_list(CTAP_getAssertion * GA, CborValue * it) if (cbor_value_get_type(it) != CborArrayType) { - printf("Error, expecting cbor array\n"); - return -1; + printf2("Error, expecting cbor array\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_enter_container(it,&arr); @@ -904,15 +912,16 @@ static int parse_allow_list(CTAP_getAssertion * GA, CborValue * it) { if (i >= ALLOW_LIST_MAX_SIZE) { - printf("Warning, out of memory for allow list, truncating.\n"); - break; + printf1("Error, out of memory for allow list.\n"); + return CTAP2_ERR_TOO_MANY_ELEMENTS; } + GA->credLen += 1; if (cbor_value_get_type(&arr) != CborMapType) { - printf("Error, CborMapType expected in allow_list\n"); - return -1; + printf2("Error, CborMapType expected in allow_list\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_map_find_value(&arr, "id", &val); @@ -920,16 +929,16 @@ static int parse_allow_list(CTAP_getAssertion * GA, CborValue * it) if (cbor_value_get_type(&val) != CborByteStringType) { - printf("Error, No valid ID field (%s)\n", cbor_value_get_type_string(&val)); - return -1; + printf2("Error, No valid ID field (%s)\n", cbor_value_get_type_string(&val)); + return CTAP2_ERR_MISSING_PARAMETER; } buflen = CREDENTIAL_ID_SIZE; cbor_value_copy_byte_string(&val, GA->creds[i].credential.id, &buflen, NULL); if (buflen != CREDENTIAL_ID_SIZE) { - printf("Error, credential is incorrect length\n"); - return -1; // maybe just skip it instead of fail? + printf2("Error, 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); @@ -937,8 +946,8 @@ static int parse_allow_list(CTAP_getAssertion * GA, CborValue * it) if (cbor_value_get_type(&val) != CborTextStringType) { - printf("Error, No valid type field\n"); - return -1; + printf2("Error, No valid type field\n"); + return CTAP2_ERR_MISSING_PARAMETER; } buflen = sizeof(type); @@ -965,7 +974,7 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d uint8_t tag[16]; if (desc->type != PUB_KEY_CRED_PUB_KEY) { - printf("unsupported credential type: %d\n", desc->type); + printf1("unsupported credential type: %d\n", desc->type); return 0; } @@ -991,8 +1000,8 @@ int ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int leng CborType type = cbor_value_get_type(&it); if (type != CborMapType) { - printf("Error, expecting cbor map\n"); - return -1; + printf2("Error, expecting cbor map\n"); + return CTAP2_ERR_INVALID_CBOR_TYPE; } ret = cbor_value_enter_container(&it,&map); @@ -1001,14 +1010,15 @@ int ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int leng ret = cbor_value_get_map_length(&it, &map_length); check_ret(ret); - printf("GA map has %d elements\n",map_length); + printf1("GA map has %d elements\n",map_length); for (i = 0; i < map_length; i++) { type = cbor_value_get_type(&map); if (type != CborIntegerType) { - printf("Error, expecting int for map key\n"); + 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); @@ -1021,58 +1031,58 @@ int ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int leng { case GA_clientDataHash: - printf("GA_clientDataHash\n"); + printf1("GA_clientDataHash\n"); ret = parse_client_data_hash(GA->clientDataHash, &map); - printf(" "); dump_hex(GA->clientDataHash, 32); + printf1(" "); dump_hex(GA->clientDataHash, 32); break; case GA_rpId: - printf("GA_rpId\n"); + printf1("GA_rpId\n"); ret = parse_rp_id(&GA->rp, &map); - printf(" ID: %s\n", GA->rp.id); + printf1(" ID: %s\n", GA->rp.id); break; case GA_allowList: - printf("GA_allowList\n"); + printf1("GA_allowList\n"); ret = parse_allow_list(GA, &map); if (ret == 0) { for (j = 0; j < GA->credLen; j++) { - printf("CRED ID (# %d): ", GA->creds[j].credential.fields.count); + printf1("CRED ID (# %d): ", GA->creds[j].credential.fields.count); dump_hex(GA->creds[j].credential.id, CREDENTIAL_ID_SIZE); if (ctap_authenticate_credential(&GA->rp, &GA->creds[j])) // warning encryption will break this { - printf(" Authenticated.\n"); + printf1(" Authenticated.\n"); } else { - printf(" NOT authentic.\n"); + printf1(" NOT authentic.\n"); } } } break; case GA_extensions: - printf("GA_extensions\n"); + printf1("GA_extensions\n"); break; case GA_options: - printf("GA_options\n"); + printf1("GA_options\n"); break; case GA_pinAuth: - printf("GA_pinAuth\n"); + printf1("GA_pinAuth\n"); break; case GA_pinProtocol: - printf("GA_pinProtocol\n"); + printf1("GA_pinProtocol\n"); break; default: - printf("invalid key %d\n", key); + printf1("invalid key %d\n", key); } if (ret != 0) { - printf("error, parsing failed\n"); + printf2("error, parsing failed\n"); return ret; } @@ -1097,7 +1107,7 @@ static int pick_first_authentic_credential(CTAP_getAssertion * GA) return -1; } -static void ctap_add_credential_descriptor(CborEncoder * map, CTAP_credentialDescriptor * cred) +static uint8_t ctap_add_credential_descriptor(CborEncoder * map, CTAP_credentialDescriptor * cred) { CborEncoder desc; int ret = cbor_encode_int(map, RESP_credential); @@ -1123,9 +1133,11 @@ static void ctap_add_credential_descriptor(CborEncoder * map, CTAP_credentialDes ret = cbor_encoder_close_container(map, &desc); check_ret(ret); + + return 0; } -void ctap_add_user_entity(CborEncoder * map, CTAP_userEntity * user) +uint8_t ctap_add_user_entity(CborEncoder * map, CTAP_userEntity * user) { CborEncoder entity; int ret = cbor_encode_int(map, RESP_publicKeyCredentialUserEntity); @@ -1154,9 +1166,10 @@ void ctap_add_user_entity(CborEncoder * map, CTAP_userEntity * user) ret = cbor_encoder_close_container(map, &entity); check_ret(ret); + return 0; } -void ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) +uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) { CTAP_getAssertion GA; uint8_t auth_data_buf[32 + 1 + 4]; @@ -1167,8 +1180,8 @@ void ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) if (ret != 0) { - printf("error, parse_get_assertion failed\n"); - return; + printf2("error, parse_get_assertion failed\n"); + return ret; } CborEncoder map; @@ -1180,13 +1193,15 @@ void ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) int pick = pick_first_authentic_credential(&GA); // TODO let this handle decryption? lazy? if (pick == -1) { - printf("Error, no authentic credential\n"); - return; + printf2("Error, no authentic credential\n"); + return CTAP2_ERR_CREDENTIAL_NOT_VALID; } - ctap_add_credential_descriptor(&map, &GA.creds[pick]); + ret = ctap_add_credential_descriptor(&map, &GA.creds[pick]); + check_ret(ret); - ctap_add_user_entity(&map, &GA.creds[pick].credential.fields.user); + ret = ctap_add_user_entity(&map, &GA.creds[pick].credential.fields.user); + check_ret(ret); crypto_ecc256_load_key(GA.creds[pick].credential.id, CREDENTIAL_ID_SIZE); @@ -1215,6 +1230,7 @@ void ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) 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++; @@ -1229,30 +1245,35 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) cbor_encoder_init(&encoder, buf, sizeof(buf), 0); _ENCODER = &encoder; - printf("cbor req: "); dump_hex(pkt_raw, length - 1); + printf1("cbor req: "); dump_hex(pkt_raw, length - 1); switch(cmd) { case CTAP_MAKE_CREDENTIAL: - printf("CTAP_MAKE_CREDENTIAL\n"); - ctap_make_credential(&encoder, pkt_raw, length - 1); + printf1("CTAP_MAKE_CREDENTIAL\n"); + status = ctap_make_credential(&encoder, pkt_raw, length - 1); + dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf)); + resp->length = cbor_encoder_get_buffer_size(&encoder, buf); break; case CTAP_GET_ASSERTION: - printf("CTAP_GET_ASSERTION\n"); - ctap_get_assertion(&encoder, pkt_raw, length - 1); + printf1("CTAP_GET_ASSERTION\n"); + status = ctap_get_assertion(&encoder, pkt_raw, length - 1); + resp->length = cbor_encoder_get_buffer_size(&encoder, buf); - printf("cbor [%d]: \n", cbor_encoder_get_buffer_size(&encoder, buf)); dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf)); + printf1("cbor [%d]: \n", cbor_encoder_get_buffer_size(&encoder, buf)); + dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf)); break; case CTAP_CANCEL: - printf("CTAP_CANCEL\n"); + printf1("CTAP_CANCEL\n"); break; case CTAP_GET_INFO: - printf("CTAP_GET_INFO\n"); - ctap_get_info(&encoder); + 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); @@ -1260,19 +1281,27 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) break; case CTAP_CLIENT_PIN: - printf("CTAP_CLIENT_PIN\n"); + printf1("CTAP_CLIENT_PIN\n"); break; case CTAP_RESET: - printf("CTAP_RESET\n"); + printf1("CTAP_RESET\n"); break; case GET_NEXT_ASSERTION: - printf("CTAP_NEXT_ASSERTION\n"); + printf1("CTAP_NEXT_ASSERTION\n"); break; default: - printf("error, invalid cmd\n"); + status = CTAP1_ERR_INVALID_COMMAND; + printf2("error, invalid cmd\n"); } - printf("cbor input structure: %d bytes\n", length - 1); - printf("cbor output structure: %d bytes\n", resp->length); - return 0; + if (status != CTAP1_ERR_SUCCESS) + { + resp->length = 0; + } + + printf1("cbor input structure: %d bytes\n", length - 1); + printf1("cbor output structure: %d bytes\n", resp->length); + return status; } + + diff --git a/ctap_errors.h b/ctap_errors.h new file mode 100644 index 0000000..896eb09 --- /dev/null +++ b/ctap_errors.h @@ -0,0 +1,51 @@ +#define CTAP1_ERR_SUCCESS 0x00 +#define CTAP1_ERR_INVALID_COMMAND 0x01 +#define CTAP1_ERR_INVALID_PARAMETER 0x02 +#define CTAP1_ERR_INVALID_LENGTH 0x03 +#define CTAP1_ERR_INVALID_SEQ 0x04 +#define CTAP1_ERR_TIMEOUT 0x05 +#define CTAP1_ERR_CHANNEL_BUSY 0x06 +#define CTAP1_ERR_LOCK_REQUIRED 0x0A +#define CTAP1_ERR_INVALID_CHANNEL 0x0B +#define CTAP2_ERR_CBOR_PARSING 0x10 +#define CTAP2_ERR_CBOR_UNEXPECTED_TYPE 0x11 +#define CTAP2_ERR_INVALID_CBOR 0x12 +#define CTAP2_ERR_INVALID_CBOR_TYPE 0x13 +#define CTAP2_ERR_MISSING_PARAMETER 0x14 +#define CTAP2_ERR_LIMIT_EXCEEDED 0x15 +#define CTAP2_ERR_UNSUPPORTED_EXTENSION 0x16 +#define CTAP2_ERR_TOO_MANY_ELEMENTS 0x17 +#define CTAP2_ERR_EXTENSION_NOT_SUPPORTED 0x18 +#define CTAP2_ERR_CREDENTIAL_EXCLUDED 0x19 +#define CTAP2_ERR_CREDENTIAL_NOT_VALID 0x20 +#define CTAP2_ERR_PROCESSING 0x21 +#define CTAP2_ERR_INVALID_CREDENTIAL 0x22 +#define CTAP2_ERR_USER_ACTION_PENDING 0x23 +#define CTAP2_ERR_OPERATION_PENDING 0x24 +#define CTAP2_ERR_NO_OPERATIONS 0x25 +#define CTAP2_ERR_UNSUPPORTED_ALGORITHM 0x26 +#define CTAP2_ERR_OPERATION_DENIED 0x27 +#define CTAP2_ERR_KEY_STORE_FULL 0x28 +#define CTAP2_ERR_NOT_BUSY 0x29 +#define CTAP2_ERR_NO_OPERATION_PENDING 0x2A +#define CTAP2_ERR_UNSUPPORTED_OPTION 0x2B +#define CTAP2_ERR_INVALID_OPTION 0x2C +#define CTAP2_ERR_KEEPALIVE_CANCEL 0x2D +#define CTAP2_ERR_NO_CREDENTIALS 0x2E +#define CTAP2_ERR_USER_ACTION_TIMEOUT 0x2F +#define CTAP2_ERR_NOT_ALLOWED 0x30 +#define CTAP2_ERR_PIN_INVALID 0x31 +#define CTAP2_ERR_PIN_BLOCKED 0x32 +#define CTAP2_ERR_PIN_AUTH_INVALID 0x33 +#define CTAP2_ERR_PIN_AUTH_BLOCKED 0x34 +#define CTAP2_ERR_PIN_NOT_SET 0x35 +#define CTAP2_ERR_PIN_REQUIRED 0x36 +#define CTAP2_ERR_PIN_POLICY_VIOLATION 0x37 +#define CTAP2_ERR_PIN_TOKEN_EXPIRED 0x38 +#define CTAP2_ERR_REQUEST_TOO_LARGE 0x39 +#define CTAP1_ERR_OTHER 0x7F +#define CTAP2_ERR_SPEC_LAST 0xDF +#define CTAP2_ERR_EXTENSION_FIRST 0xE0 +#define CTAP2_ERR_EXTENSION_LAST 0xEF +#define CTAP2_ERR_VENDOR_FIRST 0xF0 +#define CTAP2_ERR_VENDOR_LAST 0xFF diff --git a/ctaphid.c b/ctaphid.c index f194287..60ca909 100644 --- a/ctaphid.c +++ b/ctaphid.c @@ -393,6 +393,7 @@ start_over: break; case CTAPHID_PING: + printf("CTAPHID_PING\n"); ctaphid_write_buffer_init(&wb); wb.cid = active_cid; @@ -402,10 +403,10 @@ start_over: ctaphid_write(&wb, ctap_buffer, buffer_len()); ctaphid_write(&wb, NULL,0); - printf("CTAPHID_PING\n"); break; case CTAPHID_WINK: + printf("CTAPHID_WINK\n"); if (buffer_len() != 0) { @@ -422,7 +423,6 @@ start_over: ctaphid_write(&wb,NULL,0); - printf("CTAPHID_WINK\n"); break; case CTAPHID_CBOR: diff --git a/log.c b/log.c new file mode 100644 index 0000000..c05d9c2 --- /dev/null +++ b/log.c @@ -0,0 +1,14 @@ +#include +#include +#include "log.h" + +void LOG(const char * tag, int num, const char * fmt, ...) +{ +#ifdef ENABLE_FILE_LOGGING + printf("%s:%d: ", tag, num); +#endif + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} diff --git a/log.h b/log.h new file mode 100644 index 0000000..433d43e --- /dev/null +++ b/log.h @@ -0,0 +1,23 @@ +#ifndef _LOG_H +#define _LOG_H + +#define DEBUG_LEVEL 1 +#define ENABLE_FILE_LOGGING + +void LOG(const char * tag, int num, const char * fmt, ...); + +#if DEBUG_LEVEL == 1 + +#define printf1 printf +#define printf2(fmt, ...) LOG(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define printf3(fmt, ...) LOG(__FILE__, __LINE__, fmt, ##__VA_ARGS__) + +#else + +#define printf1(fmt, ...) +#define printf2(fmt, ...) +#define printf3(fmt, ...) + +#endif + +#endif