propogate errors right, add option checking
This commit is contained in:
parent
bfa4ba64ba
commit
a0f54cf142
176
ctap.c
176
ctap.c
@ -16,10 +16,17 @@
|
|||||||
#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 check_retr(r) _check_ret(r,__LINE__, __FILE__);\
|
||||||
|
if ((r) != CborNoError) return r;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define PIN_TOKEN_SIZE 16
|
#define PIN_TOKEN_SIZE 16
|
||||||
static uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
static uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||||
static uint8_t KEY_AGREEMENT_PUB[64];
|
static uint8_t KEY_AGREEMENT_PUB[64];
|
||||||
static uint8_t KEY_AGREEMENT_PRIV[32];
|
static uint8_t KEY_AGREEMENT_PRIV[32];
|
||||||
|
static uint8_t PIN_CODE_SET = 0;
|
||||||
static uint8_t PIN_CODE[64];
|
static uint8_t PIN_CODE[64];
|
||||||
static uint8_t PIN_CODE_HASH[32];
|
static uint8_t PIN_CODE_HASH[32];
|
||||||
|
|
||||||
@ -450,9 +457,9 @@ static int parse_rp_id(struct rpId * rp, CborValue * val)
|
|||||||
printf2("Error, RP_ID is too large\n");
|
printf2("Error, RP_ID is too large\n");
|
||||||
return CTAP2_ERR_LIMIT_EXCEEDED;
|
return CTAP2_ERR_LIMIT_EXCEEDED;
|
||||||
}
|
}
|
||||||
|
check_ret(ret);
|
||||||
rp->id[DOMAIN_NAME_MAX_SIZE] = 0; // Extra byte defined in struct.
|
rp->id[DOMAIN_NAME_MAX_SIZE] = 0; // Extra byte defined in struct.
|
||||||
rp->size = sz;
|
rp->size = sz;
|
||||||
check_ret(ret);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,6 +551,77 @@ static uint8_t parse_rp(struct rpId * rp, CborValue * val)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv)
|
||||||
|
{
|
||||||
|
size_t sz, map_length;
|
||||||
|
uint8_t key[8];
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
_Bool b;
|
||||||
|
CborValue map;
|
||||||
|
|
||||||
|
|
||||||
|
if (cbor_value_get_type(val) != CborMapType)
|
||||||
|
{
|
||||||
|
printf2("error, wrong type\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cbor_value_enter_container(val,&map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
ret = cbor_value_get_map_length(val, &map_length);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < map_length; i++)
|
||||||
|
{
|
||||||
|
if (cbor_value_get_type(&map) != CborTextStringType)
|
||||||
|
{
|
||||||
|
printf2("Error, expecting text string type for options map key, got %s\n", cbor_value_get_type_string(&map));
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
sz = sizeof(key);
|
||||||
|
ret = cbor_value_copy_text_string(&map, key, &sz, NULL);
|
||||||
|
|
||||||
|
if (ret == CborErrorOutOfMemory)
|
||||||
|
{
|
||||||
|
printf2("Error, rp map key is too large\n");
|
||||||
|
return CTAP2_ERR_LIMIT_EXCEEDED;
|
||||||
|
}
|
||||||
|
check_ret(ret);
|
||||||
|
key[sizeof(key) - 1] = 0;
|
||||||
|
|
||||||
|
ret = cbor_value_advance(&map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
if (cbor_value_get_type(&map) != CborBooleanType)
|
||||||
|
{
|
||||||
|
printf2("Error, expecting text string type for rp map value\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(key, "rk") == 0)
|
||||||
|
{
|
||||||
|
ret = cbor_value_get_boolean(&map, &b);
|
||||||
|
check_ret(ret);
|
||||||
|
*rk = b;
|
||||||
|
}
|
||||||
|
else if (strcmp(key, "uv") == 0)
|
||||||
|
{
|
||||||
|
ret = cbor_value_get_boolean(&map, &b);
|
||||||
|
check_ret(ret);
|
||||||
|
*uv = b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf1("ignoring key %s for RP map\n", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t 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)
|
||||||
{
|
{
|
||||||
@ -557,7 +635,7 @@ static uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder
|
|||||||
|
|
||||||
memset(MC, 0, sizeof(CTAP_makeCredential));
|
memset(MC, 0, sizeof(CTAP_makeCredential));
|
||||||
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
|
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
|
||||||
check_ret(ret);
|
check_retr(ret);
|
||||||
|
|
||||||
CborType type = cbor_value_get_type(&it);
|
CborType type = cbor_value_get_type(&it);
|
||||||
if (type != CborMapType)
|
if (type != CborMapType)
|
||||||
@ -640,15 +718,44 @@ static uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder
|
|||||||
case MC_extensions:
|
case MC_extensions:
|
||||||
printf1("CTAP_extensions\n");
|
printf1("CTAP_extensions\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MC_options:
|
case MC_options:
|
||||||
printf1("CTAP_options\n");
|
printf1("CTAP_options\n");
|
||||||
|
parse_options(&map, &MC->rk, &MC->uv);
|
||||||
break;
|
break;
|
||||||
case MC_pinAuth:
|
case MC_pinAuth:
|
||||||
printf1("CTAP_pinAuth\n");
|
printf1("CTAP_pinAuth\n");
|
||||||
|
if (cbor_value_get_type(&map) == CborByteStringType)
|
||||||
|
{
|
||||||
|
MC->pinAuthPresent = 1;
|
||||||
|
sz = 16;
|
||||||
|
ret = cbor_value_copy_byte_string(&map, MC->pinAuth, &sz, NULL);
|
||||||
|
check_ret(ret);
|
||||||
|
if (sz != 16)
|
||||||
|
{
|
||||||
|
return CTAP1_ERR_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MC_pinProtocol:
|
case MC_pinProtocol:
|
||||||
printf1("CTAP_pinProtocol\n");
|
printf1("CTAP_pinProtocol\n");
|
||||||
|
if (cbor_value_get_type(&map) == CborIntegerType)
|
||||||
|
{
|
||||||
|
ret = cbor_value_get_int_checked(&map, &MC->pinProtocol);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf1("invalid key %d\n", key);
|
printf1("invalid key %d\n", key);
|
||||||
|
|
||||||
@ -926,6 +1033,12 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
|
|||||||
return CTAP2_ERR_MISSING_PARAMETER;
|
return CTAP2_ERR_MISSING_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PIN_CODE_SET == 1 && MC.pinAuthPresent == 0)
|
||||||
|
{
|
||||||
|
printf2("pinAuth is required\n");
|
||||||
|
return CTAP2_ERR_PIN_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CborEncoder map;
|
CborEncoder map;
|
||||||
ret = cbor_encoder_create_map(encoder, &map, 3);
|
ret = cbor_encoder_create_map(encoder, &map, 3);
|
||||||
@ -940,7 +1053,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
|
|||||||
printf1("der sig [%d]: ", sigder_sz); dump_hex(sigder, sigder_sz);
|
printf1("der sig [%d]: ", sigder_sz); dump_hex(sigder, sigder_sz);
|
||||||
|
|
||||||
ret = ctap_add_attest_statement(&map, sigder, sigder_sz);
|
ret = ctap_add_attest_statement(&map, sigder, sigder_sz);
|
||||||
check_ret(ret);
|
check_retr(ret);
|
||||||
|
|
||||||
{
|
{
|
||||||
ret = cbor_encode_int(&map,RESP_fmt);
|
ret = cbor_encode_int(&map,RESP_fmt);
|
||||||
@ -1134,17 +1247,43 @@ int ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int leng
|
|||||||
case GA_extensions:
|
case GA_extensions:
|
||||||
printf1("GA_extensions\n");
|
printf1("GA_extensions\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GA_options:
|
case GA_options:
|
||||||
printf1("GA_options\n");
|
printf1("CTAP_options\n");
|
||||||
|
parse_options(&map, &GA->rk, &GA->uv);
|
||||||
break;
|
break;
|
||||||
case GA_pinAuth:
|
case GA_pinAuth:
|
||||||
printf1("GA_pinAuth\n");
|
printf1("CTAP_pinAuth\n");
|
||||||
|
if (cbor_value_get_type(&map) == CborByteStringType)
|
||||||
|
{
|
||||||
|
GA->pinAuthPresent = 1;
|
||||||
|
sz = 16;
|
||||||
|
ret = cbor_value_copy_byte_string(&map, GA->pinAuth, &sz, NULL);
|
||||||
|
check_ret(ret);
|
||||||
|
if (sz != 16)
|
||||||
|
{
|
||||||
|
return CTAP1_ERR_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case GA_pinProtocol:
|
case GA_pinProtocol:
|
||||||
printf1("GA_pinProtocol\n");
|
printf1("CTAP_pinProtocol\n");
|
||||||
|
if (cbor_value_get_type(&map) == CborIntegerType)
|
||||||
|
{
|
||||||
|
ret = cbor_value_get_int_checked(&map, &GA->pinProtocol);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
printf1("invalid key %d\n", key);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@ -1251,6 +1390,13 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PIN_CODE_SET == 1 && GA.pinAuthPresent == 0)
|
||||||
|
{
|
||||||
|
printf2("pinAuth is required\n");
|
||||||
|
return CTAP2_ERR_PIN_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CborEncoder map;
|
CborEncoder map;
|
||||||
ret = cbor_encoder_create_map(encoder, &map, 5);
|
ret = cbor_encoder_create_map(encoder, &map, 5);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
@ -1265,10 +1411,10 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = ctap_add_credential_descriptor(&map, &GA.creds[pick]);
|
ret = ctap_add_credential_descriptor(&map, &GA.creds[pick]);
|
||||||
check_ret(ret);
|
check_retr(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);
|
check_retr(ret);
|
||||||
|
|
||||||
crypto_ecc256_load_key(GA.creds[pick].credential.id, CREDENTIAL_ID_SIZE);
|
crypto_ecc256_load_key(GA.creds[pick].credential.id, CREDENTIAL_ID_SIZE);
|
||||||
|
|
||||||
@ -1488,7 +1634,7 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
|
|||||||
case CP_keyAgreement:
|
case CP_keyAgreement:
|
||||||
printf("CP_keyAgreement\n");
|
printf("CP_keyAgreement\n");
|
||||||
ret = parse_cose_key(&map, CP->keyAgreement.pubkey.x, CP->keyAgreement.pubkey.y, &CP->keyAgreement.kty, &CP->keyAgreement.crv);
|
ret = parse_cose_key(&map, CP->keyAgreement.pubkey.x, CP->keyAgreement.pubkey.y, &CP->keyAgreement.kty, &CP->keyAgreement.crv);
|
||||||
check_ret(ret);
|
check_retr(ret);
|
||||||
CP->keyAgreementPresent = 1;
|
CP->keyAgreementPresent = 1;
|
||||||
break;
|
break;
|
||||||
case CP_pinAuth:
|
case CP_pinAuth:
|
||||||
@ -1550,11 +1696,12 @@ uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, u
|
|||||||
|
|
||||||
crypto_aes256_decrypt(pinHashEnc, 16);
|
crypto_aes256_decrypt(pinHashEnc, 16);
|
||||||
|
|
||||||
printf("platform-pin-hash: "); dump_hex(pinHashEnc, 16);
|
|
||||||
printf("authentic-pin-hash: "); dump_hex(PIN_CODE_HASH, 16);
|
|
||||||
|
|
||||||
if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0)
|
if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0)
|
||||||
{
|
{
|
||||||
|
printf2("Pin does not match!\n");
|
||||||
|
printf2("platform-pin-hash: "); dump_hex(pinHashEnc, 16);
|
||||||
|
printf2("authentic-pin-hash: "); dump_hex(PIN_CODE_HASH, 16);
|
||||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||||
return CTAP2_ERR_PIN_INVALID;
|
return CTAP2_ERR_PIN_INVALID;
|
||||||
}
|
}
|
||||||
@ -1632,7 +1779,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
|
|
||||||
ret = ctap_add_pin_if_verified(&map, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinHashEnc);
|
ret = ctap_add_pin_if_verified(&map, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinHashEnc);
|
||||||
check_ret(ret);
|
check_retr(ret);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1740,6 +1887,7 @@ void ctap_init()
|
|||||||
// TODO this should be stored in flash memory
|
// TODO this should be stored in flash memory
|
||||||
memset(PIN_CODE,0,sizeof(PIN_CODE));
|
memset(PIN_CODE,0,sizeof(PIN_CODE));
|
||||||
memmove(PIN_CODE, "1234", 4);
|
memmove(PIN_CODE, "1234", 4);
|
||||||
|
PIN_CODE_SET = 1;
|
||||||
|
|
||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(PIN_CODE, 4);
|
crypto_sha256_update(PIN_CODE, 4);
|
||||||
|
17
ctap.h
17
ctap.h
@ -158,7 +158,12 @@ typedef struct
|
|||||||
uint8_t publicKeyCredentialType;
|
uint8_t publicKeyCredentialType;
|
||||||
int32_t COSEAlgorithmIdentifier;
|
int32_t COSEAlgorithmIdentifier;
|
||||||
|
|
||||||
uint8_t pinProtocol;
|
uint8_t rk;
|
||||||
|
uint8_t uv;
|
||||||
|
|
||||||
|
uint8_t pinAuth[16];
|
||||||
|
uint8_t pinAuthPresent;
|
||||||
|
int pinProtocol;
|
||||||
|
|
||||||
} CTAP_makeCredential;
|
} CTAP_makeCredential;
|
||||||
|
|
||||||
@ -175,8 +180,16 @@ typedef struct
|
|||||||
|
|
||||||
struct rpId rp;
|
struct rpId rp;
|
||||||
|
|
||||||
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
|
||||||
int credLen;
|
int credLen;
|
||||||
|
|
||||||
|
uint8_t rk;
|
||||||
|
uint8_t uv;
|
||||||
|
|
||||||
|
uint8_t pinAuth[16];
|
||||||
|
uint8_t pinAuthPresent;
|
||||||
|
int pinProtocol;
|
||||||
|
|
||||||
|
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
||||||
} CTAP_getAssertion;
|
} CTAP_getAssertion;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
Loading…
x
Reference in New Issue
Block a user