progress on pin codes

This commit is contained in:
Conor Patrick 2018-05-16 22:44:31 -04:00
parent 4b35a37613
commit 162539a561
5 changed files with 255 additions and 21 deletions

View File

@ -107,6 +107,15 @@ void crypto_ecc256_load_key(uint8_t * data, int len)
_signing_key = privkey;
}
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
{
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
{
printf("Error, uECC_make_key failed\n");
exit(1);
}
}
const uint8_t attestation_cert_der[] =
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"

View File

@ -19,6 +19,7 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig);
void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey);
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey);
extern const uint8_t attestation_cert_der[];
extern const uint16_t attestation_cert_der_size;

249
ctap.c
View File

@ -18,6 +18,9 @@
#define PIN_TOKEN_SIZE 16
static uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
static uint8_t KEY_AGREEMENT_PUB[64];
static uint8_t KEY_AGREEMENT_PRIV[32];
static uint8_t PIN_CODE[64];
static CborEncoder * _ENCODER;
static void _check_ret(CborError ret, int line, const char * filename)
@ -661,32 +664,14 @@ static uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder
return 0;
}
static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input, int len, uint8_t credtype, int32_t algtype)
static int ctap_add_cose_key(CborEncoder * cose_key, uint8_t * x, uint8_t * y, uint8_t credtype, int32_t algtype)
{
uint8_t x[32], y[32];
int ret;
CborEncoder map;
ret = cbor_encoder_create_map(cose_key, &map, 5);
int extra = cbor_encoder_get_extra_bytes_needed(&map);
printf1(" extra? %d\n", extra);
check_ret(ret);
if (credtype != PUB_KEY_CRED_PUB_KEY)
{
printf2("Error, pubkey credential type not supported\n");
return -1;
}
switch(algtype)
{
case COSE_ALG_ES256:
crypto_ecc256_init();
crypto_ecc256_derive_public_key(hmac_input, len, x, y);
break;
default:
printf2("Error, COSE alg %d not supported\n", algtype);
return -1;
}
{
ret = cbor_encode_int(&map, COSE_KEY_LABEL_KTY);
@ -726,6 +711,27 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input,
ret = cbor_encoder_close_container(cose_key, &map);
check_ret(ret);
}
static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input, int len, uint8_t credtype, int32_t algtype)
{
uint8_t x[32], y[32];
if (credtype != PUB_KEY_CRED_PUB_KEY)
{
printf2("Error, pubkey credential type not supported\n");
return -1;
}
switch(algtype)
{
case COSE_ALG_ES256:
crypto_ecc256_derive_public_key(hmac_input, len, x, y);
break;
default:
printf2("Error, COSE alg %d not supported\n", algtype);
return -1;
}
ctap_add_cose_key(cose_key, x, y, credtype, algtype);
}
void make_auth_tag(struct rpId * rp, CTAP_userEntity * user, uint32_t count, uint8_t * tag)
@ -1286,6 +1292,126 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
}
uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int * crv)
{
CborValue map;
size_t map_length;
size_t ptsz;
int i,ret,key;
int xkey = 0,ykey = 0;
*kty = 0;
*crv = 0;
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("cose key has %d elements\n",map_length);
for (i = 0; i < map_length; i++)
{
if (cbor_value_get_type(&map) != 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);
switch(key)
{
case COSE_KEY_LABEL_KTY:
printf1("COSE_KEY_LABEL_KTY\n");
if (cbor_value_get_type(&map) == CborIntegerType)
{
ret = cbor_value_get_int_checked(&map, kty);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case COSE_KEY_LABEL_ALG:
printf1("COSE_KEY_LABEL_ALG\n");
break;
case COSE_KEY_LABEL_CRV:
printf1("COSE_KEY_LABEL_CRV\n");
if (cbor_value_get_type(&map) == CborIntegerType)
{
ret = cbor_value_get_int_checked(&map, crv);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case COSE_KEY_LABEL_X:
printf1("COSE_KEY_LABEL_X\n");
if (cbor_value_get_type(&map) == CborByteStringType)
{
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;
case COSE_KEY_LABEL_Y:
printf1("COSE_KEY_LABEL_Y\n");
if (cbor_value_get_type(&map) == CborByteStringType)
{
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;
default:
printf1("Warning, unrecognized cose key option %d\n", key);
}
ret = cbor_value_advance(&map);
check_ret(ret);
}
if (xkey == 0 || ykey == 0 || *kty == 0 || *crv == 0)
{
return CTAP2_ERR_MISSING_PARAMETER;
}
return 0;
}
int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
{
@ -1335,12 +1461,33 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
{
case CP_pinProtocol:
printf("CP_pinProtocol\n");
if (cbor_value_get_type(&map) == CborIntegerType)
{
cbor_value_get_int_checked(&map, &CP->pinProtocol);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case CP_subCommand:
printf("CP_subCommand\n");
if (cbor_value_get_type(&map) == CborIntegerType)
{
cbor_value_get_int_checked(&map, &CP->subCommand);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case CP_keyAgreement:
printf("CP_keyAgreement\n");
ret = parse_cose_key(&map, CP->keyAgreement.x, CP->keyAgreement.y, &CP->keyAgreement.kty, &CP->keyAgreement.crv);
check_ret(ret);
break;
case CP_pinAuth:
printf("CP_pinAuth\n");
@ -1374,6 +1521,7 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
{
CTAP_clientPin CP;
CborEncoder map;
int ret = ctap_parse_client_pin(&CP,request,length);
if (ret != 0)
@ -1381,6 +1529,62 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
printf2("error, parse_client_pin failed\n");
return ret;
}
if (CP.pinProtocol != 1 || CP.subCommand == 0)
{
return CTAP1_ERR_OTHER;
}
ret = cbor_encoder_create_map(encoder, &map, 1);
check_ret(ret);
switch(CP.subCommand)
{
case CP_cmdGetRetries:
printf("CP_cmdGetRetries\n");
ret = cbor_encode_int(&map, 99);
check_ret(ret);
cbor_encode_int(&map, 99);
check_ret(ret);
break;
case CP_cmdGetKeyAgreement:
printf("CP_cmdGetKeyAgreement\n");
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;
case CP_cmdSetPin:
printf("CP_cmdSetPin\n");
ret = cbor_encode_int(&map, 99);
check_ret(ret);
cbor_encode_int(&map, 99);
check_ret(ret);
break;
case CP_cmdChangePin:
printf("CP_cmdChangePin\n");
ret = cbor_encode_int(&map, 99);
check_ret(ret);
cbor_encode_int(&map, 99);
check_ret(ret);
break;
case CP_cmdGetPinToken:
printf("CP_cmdGetPinToken\n");
ret = cbor_encode_int(&map, 99);
check_ret(ret);
cbor_encode_int(&map, 99);
check_ret(ret);
break;
default:
printf2("Error, invalid client pin subcommand\n");
return CTAP1_ERR_OTHER;
}
ret = cbor_encoder_close_container(encoder, &map);
check_ret(ret);
return 0;
}
@ -1439,6 +1643,8 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
case CTAP_CLIENT_PIN:
printf1("CTAP_CLIENT_PIN\n");
status = ctap_client_pin(&encoder, pkt_raw, length);
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
dump_hex(buf, cbor_encoder_get_buffer_size(&encoder, buf));
break;
case CTAP_RESET:
printf1("CTAP_RESET\n");
@ -1463,10 +1669,15 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
void ctap_init()
{
crypto_ecc256_init();
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
{
printf2("Error, rng failed\n");
exit(1);
}
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
}

14
ctap.h
View File

@ -33,6 +33,11 @@
#define CP_pinProtocol 0x01
#define CP_subCommand 0x02
#define CP_cmdGetRetries 0x01
#define CP_cmdGetKeyAgreement 0x02
#define CP_cmdSetPin 0x03
#define CP_cmdChangePin 0x04
#define CP_cmdGetPinToken 0x05
#define CP_keyAgreement 0x03
#define CP_pinAuth 0x04
#define CP_newPinEnc 0x05
@ -56,7 +61,9 @@
#define RESP_publicKeyCredentialUserEntity 0x04
#define RESP_numberOfCredentials 0x05
#define RESP_keyAgreement 0x01
#define RESP_pinToken 0x02
#define RESP_retries 0x03
#define PARAM_clientDataHash (1 << 0)
@ -178,7 +185,10 @@ typedef struct
int subCommand;
struct
{
uint8_t x[32];
uint8_t y[32];
int kty;
int crv;
} keyAgreement;
uint8_t pinAuth[16];
uint8_t newPinEnc[NEW_PIN_ENC_MAX_SIZE];

3
main.c
View File

@ -6,6 +6,7 @@
#include "usbhid.h"
#include "ctaphid.h"
#include "util.h"
#include "ctap.h"
static void check_ret(CborError ret)
@ -34,6 +35,8 @@ int main(int argc, char * argv[])
usbhid_init();
printf("init ctaphid\n");
ctaphid_init();
printf("init ctap\n");
ctap_init();
int count = 0;
uint8_t hidmsg[64];