refactor, bugfix, add more pin command support
This commit is contained in:
parent
8020e868f9
commit
5bac402118
305
ctap.c
305
ctap.c
@ -25,8 +25,9 @@ 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_SET = 0;
|
||||||
static uint8_t PIN_CODE[64];
|
static uint8_t PIN_CODE[NEW_PIN_ENC_MAX_SIZE];
|
||||||
static uint8_t PIN_CODE_HASH[32];
|
static uint8_t PIN_CODE_HASH[32];
|
||||||
|
static uint8_t DEVICE_LOCKOUT = 0;
|
||||||
|
|
||||||
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)
|
||||||
@ -242,28 +243,6 @@ uint8_t ctap_get_info(CborEncoder * encoder)
|
|||||||
return CTAP1_ERR_SUCCESS;
|
return CTAP1_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t parse_client_data_hash(uint8_t * clientDataHash, CborValue * val)
|
|
||||||
{
|
|
||||||
size_t sz;
|
|
||||||
int ret;
|
|
||||||
if (cbor_value_get_type(val) != CborByteStringType)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR,"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)
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR,"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);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
|
static uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
|
||||||
{
|
{
|
||||||
@ -465,6 +444,27 @@ static uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * v
|
|||||||
return CTAP2_ERR_UNSUPPORTED_ALGORITHM;
|
return CTAP2_ERR_UNSUPPORTED_ALGORITHM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len)
|
||||||
|
{
|
||||||
|
size_t sz;
|
||||||
|
int ret;
|
||||||
|
if (cbor_value_get_type(map) == CborByteStringType)
|
||||||
|
{
|
||||||
|
sz = len;
|
||||||
|
ret = cbor_value_copy_byte_string(map, dst, &sz, NULL);
|
||||||
|
check_ret(ret);
|
||||||
|
if (sz != len)
|
||||||
|
{
|
||||||
|
return CTAP1_ERR_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int parse_rp_id(struct rpId * rp, CborValue * val)
|
static int parse_rp_id(struct rpId * rp, CborValue * val)
|
||||||
{
|
{
|
||||||
@ -691,7 +691,7 @@ static uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder
|
|||||||
case MC_clientDataHash:
|
case MC_clientDataHash:
|
||||||
printf1(TAG_MC,"CTAP_clientDataHash\n");
|
printf1(TAG_MC,"CTAP_clientDataHash\n");
|
||||||
|
|
||||||
ret = parse_client_data_hash(MC->clientDataHash, &map);
|
ret = parse_fixed_byte_string(&map, MC->clientDataHash, CLIENT_DATA_HASH_SIZE);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
MC->paramsParsed |= PARAM_clientDataHash;
|
MC->paramsParsed |= PARAM_clientDataHash;
|
||||||
@ -739,25 +739,15 @@ static uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder
|
|||||||
|
|
||||||
case MC_options:
|
case MC_options:
|
||||||
printf1(TAG_MC,"CTAP_options\n");
|
printf1(TAG_MC,"CTAP_options\n");
|
||||||
parse_options(&map, &MC->rk, &MC->uv);
|
ret = parse_options(&map, &MC->rk, &MC->uv);
|
||||||
|
check_retr(ret);
|
||||||
break;
|
break;
|
||||||
case MC_pinAuth:
|
case MC_pinAuth:
|
||||||
printf1(TAG_MC,"CTAP_pinAuth\n");
|
printf1(TAG_MC,"CTAP_pinAuth\n");
|
||||||
if (cbor_value_get_type(&map) == CborByteStringType)
|
|
||||||
{
|
ret = parse_fixed_byte_string(&map, MC->pinAuth, 16);
|
||||||
|
check_retr(ret);
|
||||||
MC->pinAuthPresent = 1;
|
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:
|
||||||
@ -1237,7 +1227,8 @@ int ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int leng
|
|||||||
case GA_clientDataHash:
|
case GA_clientDataHash:
|
||||||
printf1(TAG_GA,"GA_clientDataHash\n");
|
printf1(TAG_GA,"GA_clientDataHash\n");
|
||||||
|
|
||||||
ret = parse_client_data_hash(GA->clientDataHash, &map);
|
ret = parse_fixed_byte_string(&map, GA->clientDataHash, CLIENT_DATA_HASH_SIZE);
|
||||||
|
check_retr(ret);
|
||||||
|
|
||||||
printf1(TAG_GA," "); dump_hex1(TAG_GA, GA->clientDataHash, 32);
|
printf1(TAG_GA," "); dump_hex1(TAG_GA, GA->clientDataHash, 32);
|
||||||
break;
|
break;
|
||||||
@ -1274,25 +1265,15 @@ int ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int leng
|
|||||||
|
|
||||||
case GA_options:
|
case GA_options:
|
||||||
printf1(TAG_GA,"CTAP_options\n");
|
printf1(TAG_GA,"CTAP_options\n");
|
||||||
parse_options(&map, &GA->rk, &GA->uv);
|
ret = parse_options(&map, &GA->rk, &GA->uv);
|
||||||
|
check_retr(ret);
|
||||||
break;
|
break;
|
||||||
case GA_pinAuth:
|
case GA_pinAuth:
|
||||||
printf1(TAG_GA,"CTAP_pinAuth\n");
|
printf1(TAG_GA,"CTAP_pinAuth\n");
|
||||||
if (cbor_value_get_type(&map) == CborByteStringType)
|
|
||||||
{
|
ret = parse_fixed_byte_string(&map, GA->pinAuth, 16);
|
||||||
|
check_retr(ret);
|
||||||
GA->pinAuthPresent = 1;
|
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:
|
||||||
@ -1539,40 +1520,16 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
|
|||||||
break;
|
break;
|
||||||
case COSE_KEY_LABEL_X:
|
case COSE_KEY_LABEL_X:
|
||||||
printf1(TAG_PARSE,"COSE_KEY_LABEL_X\n");
|
printf1(TAG_PARSE,"COSE_KEY_LABEL_X\n");
|
||||||
if (cbor_value_get_type(&map) == CborByteStringType)
|
ret = parse_fixed_byte_string(&map, x, 32);
|
||||||
{
|
check_retr(ret);
|
||||||
xkey = 1;
|
xkey = 1;
|
||||||
ptsz = 32;
|
|
||||||
ret = cbor_value_copy_byte_string(&map, x, &ptsz, NULL);
|
|
||||||
check_ret(ret);
|
|
||||||
if (ptsz != 32)
|
|
||||||
{
|
|
||||||
return CTAP1_ERR_OTHER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case COSE_KEY_LABEL_Y:
|
case COSE_KEY_LABEL_Y:
|
||||||
printf1(TAG_PARSE,"COSE_KEY_LABEL_Y\n");
|
printf1(TAG_PARSE,"COSE_KEY_LABEL_Y\n");
|
||||||
if (cbor_value_get_type(&map) == CborByteStringType)
|
ret = parse_fixed_byte_string(&map, y, 32);
|
||||||
{
|
check_retr(ret);
|
||||||
ykey = 1;
|
ykey = 1;
|
||||||
ptsz = 32;
|
|
||||||
ret = cbor_value_copy_byte_string(&map, y, &ptsz, NULL);
|
|
||||||
check_ret(ret);
|
|
||||||
if (ptsz != 32)
|
|
||||||
{
|
|
||||||
return CTAP1_ERR_OTHER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1668,28 +1625,39 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
|
|||||||
break;
|
break;
|
||||||
case CP_pinAuth:
|
case CP_pinAuth:
|
||||||
printf1(TAG_CP,"CP_pinAuth\n");
|
printf1(TAG_CP,"CP_pinAuth\n");
|
||||||
|
|
||||||
|
ret = parse_fixed_byte_string(&map, CP->pinAuth, 16);
|
||||||
|
check_retr(ret);
|
||||||
|
CP->pinAuthPresent = 1;
|
||||||
break;
|
break;
|
||||||
case CP_newPinEnc:
|
case CP_newPinEnc:
|
||||||
printf1(TAG_CP,"CP_newPinEnc\n");
|
printf1(TAG_CP,"CP_newPinEnc\n");
|
||||||
break;
|
|
||||||
case CP_pinHashEnc:
|
|
||||||
printf1(TAG_CP,"CP_pinHashEnc\n");
|
|
||||||
|
|
||||||
if (cbor_value_get_type(&map) == CborByteStringType)
|
if (cbor_value_get_type(&map) == CborByteStringType)
|
||||||
{
|
{
|
||||||
CP->pinHashEncPresent = 1;
|
ret = cbor_value_calculate_string_length(&map, &sz);
|
||||||
sz = 16;
|
|
||||||
ret = cbor_value_copy_byte_string(&map, CP->pinHashEnc, &sz, NULL);
|
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
if (sz != 16)
|
if (sz > NEW_PIN_ENC_MAX_SIZE)
|
||||||
{
|
{
|
||||||
return CTAP1_ERR_OTHER;
|
return CTAP1_ERR_OTHER;
|
||||||
}
|
}
|
||||||
|
CP->newPinEncSize = sz;
|
||||||
|
sz = NEW_PIN_ENC_MAX_SIZE;
|
||||||
|
ret = cbor_value_copy_byte_string(&map, CP->newPinEnc, &sz, NULL);
|
||||||
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CP_pinHashEnc:
|
||||||
|
printf1(TAG_CP,"CP_pinHashEnc\n");
|
||||||
|
|
||||||
|
ret = parse_fixed_byte_string(&map, CP->pinHashEnc, 16);
|
||||||
|
check_retr(ret);
|
||||||
|
CP->pinHashEncPresent = 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CP_getKeyAgreement:
|
case CP_getKeyAgreement:
|
||||||
printf1(TAG_CP,"CP_getKeyAgreement\n");
|
printf1(TAG_CP,"CP_getKeyAgreement\n");
|
||||||
@ -1710,6 +1678,62 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platform_pubkey, uint8_t * pinAuth)
|
||||||
|
{
|
||||||
|
uint8_t shared_secret[32];
|
||||||
|
uint8_t hmac[32];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (len < 64)
|
||||||
|
{
|
||||||
|
return CTAP1_ERR_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
crypto_ecc256_shared_secret(platform_pubkey, KEY_AGREEMENT_PRIV, shared_secret);
|
||||||
|
|
||||||
|
crypto_sha256_init();
|
||||||
|
crypto_sha256_update(shared_secret, 32);
|
||||||
|
crypto_sha256_final(shared_secret);
|
||||||
|
|
||||||
|
crypto_sha256_hmac(shared_secret, 32, pinEnc, len, hmac);
|
||||||
|
|
||||||
|
if (memcmp(hmac, pinAuth, 16) != 0)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"pinAuth failed for update pin\n");
|
||||||
|
dump_hex1(TAG_ERR, hmac,16);
|
||||||
|
dump_hex1(TAG_ERR, pinAuth,16);
|
||||||
|
return CTAP2_ERR_PIN_AUTH_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_aes256_init(shared_secret);
|
||||||
|
|
||||||
|
while((len & 0xf) != 0) // round up to nearest AES block size multiple
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_aes256_decrypt(pinEnc, len);
|
||||||
|
|
||||||
|
ret = strnlen(pinEnc, NEW_PIN_ENC_MAX_SIZE);
|
||||||
|
if (ret == NEW_PIN_ENC_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");
|
||||||
|
return CTAP2_ERR_PIN_POLICY_VIOLATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctap_update_pin(pinEnc, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, uint8_t * pinHashEnc)
|
uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, uint8_t * pinHashEnc)
|
||||||
{
|
{
|
||||||
uint8_t shared_secret[32];
|
uint8_t shared_secret[32];
|
||||||
@ -1733,6 +1757,7 @@ uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, u
|
|||||||
printf2(TAG_ERR,"authentic-pin-hash: "); dump_hex1(TAG_ERR, PIN_CODE_HASH, 16);
|
printf2(TAG_ERR,"authentic-pin-hash: "); dump_hex1(TAG_ERR, PIN_CODE_HASH, 16);
|
||||||
// Generate new keyAgreement pair
|
// Generate new keyAgreement pair
|
||||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||||
|
ctap_decrement_pin_attempts();
|
||||||
return CTAP2_ERR_PIN_INVALID;
|
return CTAP2_ERR_PIN_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1754,6 +1779,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
CborEncoder map;
|
CborEncoder map;
|
||||||
int ret = ctap_parse_client_pin(&CP,request,length);
|
int ret = ctap_parse_client_pin(&CP,request,length);
|
||||||
|
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"error, parse_client_pin failed\n");
|
printf2(TAG_ERR,"error, parse_client_pin failed\n");
|
||||||
@ -1765,44 +1791,50 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
return CTAP1_ERR_OTHER;
|
return CTAP1_ERR_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cbor_encoder_create_map(encoder, &map, 1);
|
int num_map = (CP.getRetries ? 1 : 0);
|
||||||
check_ret(ret);
|
|
||||||
|
|
||||||
switch(CP.subCommand)
|
switch(CP.subCommand)
|
||||||
{
|
{
|
||||||
case CP_cmdGetRetries:
|
case CP_cmdGetRetries:
|
||||||
printf1(TAG_CP,"CP_cmdGetRetries\n");
|
printf1(TAG_CP,"CP_cmdGetRetries\n");
|
||||||
ret = cbor_encode_int(&map, 99);
|
ret = cbor_encoder_create_map(encoder, &map, 1);
|
||||||
check_ret(ret);
|
|
||||||
cbor_encode_int(&map, 99);
|
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
|
|
||||||
|
CP.getRetries = 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CP_cmdGetKeyAgreement:
|
case CP_cmdGetKeyAgreement:
|
||||||
printf1(TAG_CP,"CP_cmdGetKeyAgreement\n");
|
printf1(TAG_CP,"CP_cmdGetKeyAgreement\n");
|
||||||
|
num_map++;
|
||||||
|
ret = cbor_encoder_create_map(encoder, &map, num_map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
ret = cbor_encode_int(&map, RESP_keyAgreement);
|
||||||
|
check_ret(ret);
|
||||||
|
ret = ctap_add_cose_key(&map, KEY_AGREEMENT_PUB, KEY_AGREEMENT_PUB+32, PUB_KEY_CRED_PUB_KEY, COSE_ALG_ES256);
|
||||||
|
check_retr(ret);
|
||||||
|
|
||||||
cbor_encode_int(&map, RESP_keyAgreement);
|
|
||||||
ctap_add_cose_key(&map, KEY_AGREEMENT_PUB, KEY_AGREEMENT_PUB+32, PUB_KEY_CRED_PUB_KEY, COSE_ALG_ES256);
|
|
||||||
break;
|
break;
|
||||||
case CP_cmdSetPin:
|
case CP_cmdSetPin:
|
||||||
printf1(TAG_CP,"CP_cmdSetPin\n");
|
printf1(TAG_CP,"CP_cmdSetPin\n");
|
||||||
ret = cbor_encode_int(&map, 99);
|
ret = ctap_update_pin_if_verified(CP.newPinEnc, CP.newPinEncSize, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinAuth);
|
||||||
check_ret(ret);
|
check_retr(ret);
|
||||||
cbor_encode_int(&map, 99);
|
|
||||||
check_ret(ret);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CP_cmdChangePin:
|
case CP_cmdChangePin:
|
||||||
printf1(TAG_CP,"CP_cmdChangePin\n");
|
printf1(TAG_CP,"CP_cmdChangePin\n");
|
||||||
ret = cbor_encode_int(&map, 99);
|
return CTAP1_ERR_INVALID_COMMAND;
|
||||||
check_ret(ret);
|
|
||||||
cbor_encode_int(&map, 99);
|
|
||||||
check_ret(ret);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CP_cmdGetPinToken:
|
case CP_cmdGetPinToken:
|
||||||
|
num_map++;
|
||||||
|
ret = cbor_encoder_create_map(encoder, &map, num_map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
printf1(TAG_CP,"CP_cmdGetPinToken\n");
|
printf1(TAG_CP,"CP_cmdGetPinToken\n");
|
||||||
if (CP.keyAgreementPresent == 0 || CP.pinHashEncPresent == 0)
|
if (CP.keyAgreementPresent == 0 || CP.pinHashEncPresent == 0)
|
||||||
{
|
{
|
||||||
|
printf2(TAG_ERR,"Error, missing keyAgreement or pinHashEnc for cmdGetPin\n");
|
||||||
return CTAP2_ERR_MISSING_PARAMETER;
|
return CTAP2_ERR_MISSING_PARAMETER;
|
||||||
}
|
}
|
||||||
ret = cbor_encode_int(&map, RESP_pinToken);
|
ret = cbor_encode_int(&map, RESP_pinToken);
|
||||||
@ -1812,13 +1844,25 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
check_retr(ret);
|
check_retr(ret);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf2(TAG_ERR,"Error, invalid client pin subcommand\n");
|
printf2(TAG_ERR,"Error, invalid client pin subcommand\n");
|
||||||
return CTAP1_ERR_OTHER;
|
return CTAP1_ERR_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CP.getRetries)
|
||||||
|
{
|
||||||
|
ret = cbor_encode_int(&map, RESP_retries);
|
||||||
|
check_ret(ret);
|
||||||
|
ret = cbor_encode_int(&map, ctap_leftover_pin_attempts());
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_map)
|
||||||
|
{
|
||||||
ret = cbor_encoder_close_container(encoder, &map);
|
ret = cbor_encoder_close_container(encoder, &map);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1905,6 +1949,9 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
|||||||
void ctap_init()
|
void ctap_init()
|
||||||
{
|
{
|
||||||
crypto_ecc256_init();
|
crypto_ecc256_init();
|
||||||
|
ctap_reset_pin_attempts();
|
||||||
|
|
||||||
|
DEVICE_LOCKOUT = 0;
|
||||||
|
|
||||||
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
|
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
|
||||||
{
|
{
|
||||||
@ -1913,13 +1960,51 @@ void ctap_init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO this doesn't have to happen at every boot up
|
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)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR, "Update pin fail length\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
memset(PIN_CODE,0,sizeof(PIN_CODE));
|
memset(PIN_CODE,0,sizeof(PIN_CODE));
|
||||||
memmove(PIN_CODE, "1234", 4);
|
memmove(PIN_CODE, pin, len);
|
||||||
PIN_CODE_SET = 1;
|
|
||||||
|
|
||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(PIN_CODE, 4);
|
crypto_sha256_update(PIN_CODE, len);
|
||||||
crypto_sha256_final(PIN_CODE_HASH);
|
crypto_sha256_final(PIN_CODE_HASH);
|
||||||
|
|
||||||
|
PIN_CODE_SET = 1;
|
||||||
|
|
||||||
|
printf1(TAG_CTAP, "New pin set: %s\n", PIN_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO flash
|
||||||
|
static int8_t _flash_tries;
|
||||||
|
uint8_t ctap_decrement_pin_attempts()
|
||||||
|
{
|
||||||
|
if (_flash_tries > 0)
|
||||||
|
{
|
||||||
|
_flash_tries--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEVICE_LOCKOUT = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ctap_leftover_pin_attempts()
|
||||||
|
{
|
||||||
|
return _flash_tries;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctap_reset_pin_attempts()
|
||||||
|
{
|
||||||
|
_flash_tries = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
10
ctap.h
10
ctap.h
@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
#define ALLOW_LIST_MAX_SIZE 20
|
#define ALLOW_LIST_MAX_SIZE 20
|
||||||
|
|
||||||
#define NEW_PIN_ENC_MAX_SIZE 256
|
#define NEW_PIN_ENC_MAX_SIZE 256 // includes NULL terminator
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -208,7 +208,9 @@ typedef struct
|
|||||||
} keyAgreement;
|
} keyAgreement;
|
||||||
uint8_t keyAgreementPresent;
|
uint8_t keyAgreementPresent;
|
||||||
uint8_t pinAuth[16];
|
uint8_t pinAuth[16];
|
||||||
|
uint8_t pinAuthPresent;
|
||||||
uint8_t newPinEnc[NEW_PIN_ENC_MAX_SIZE];
|
uint8_t newPinEnc[NEW_PIN_ENC_MAX_SIZE];
|
||||||
|
int newPinEncSize;
|
||||||
uint8_t pinHashEnc[16];
|
uint8_t pinHashEnc[16];
|
||||||
uint8_t pinHashEncPresent;
|
uint8_t pinHashEncPresent;
|
||||||
int getKeyAgreement;
|
int getKeyAgreement;
|
||||||
@ -221,6 +223,12 @@ 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)
|
// Run ctap related power-up procedures (init pinToken, generate shared secret)
|
||||||
void ctap_init();
|
void ctap_init();
|
||||||
|
|
||||||
|
void ctap_update_pin(uint8_t * pin, int len);
|
||||||
|
uint8_t ctap_decrement_pin_attempts();
|
||||||
|
int8_t ctap_leftover_pin_attempts();
|
||||||
|
void ctap_reset_pin_attempts();
|
||||||
|
|
||||||
|
|
||||||
// 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();
|
||||||
|
1
main.c
1
main.c
@ -28,6 +28,7 @@ int main(int argc, char * argv[])
|
|||||||
TAG_CP |
|
TAG_CP |
|
||||||
TAG_CTAP |
|
TAG_CTAP |
|
||||||
TAG_PARSE |
|
TAG_PARSE |
|
||||||
|
TAG_DUMP|
|
||||||
TAG_ERR
|
TAG_ERR
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user