fix infrequent der formatting bug. start excludelist

This commit is contained in:
Conor Patrick 2018-05-24 21:26:46 -04:00
parent 644ceaef63
commit 10e50bea48
5 changed files with 141 additions and 78 deletions

83
ctap.c
View File

@ -344,6 +344,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
// @return length of der signature
int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHash, uint8_t * hashbuf, uint8_t * sigbuf, uint8_t * sigder)
{
int i;
// calculate attestation sig
crypto_sha256_init();
crypto_sha256_update(data, datalen);
@ -351,27 +352,38 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa
crypto_sha256_final(hashbuf);
printf1(TAG_GREEN, "sha256: "); dump_hex1(TAG_DUMP,hashbuf,32);
crypto_ecc256_sign(hashbuf, 32, sigbuf);
// Need to caress into dumb der format ..
uint8_t pad_s = (sigbuf[32] & 0x80) == 0x80;
uint8_t pad_r = (sigbuf[0] & 0x80) == 0x80;
int8_t pad_s = ((sigbuf[32 + lead_s] & 0x80) == 0x80); // Is MSBit a 1?
int8_t pad_r = ((sigbuf[0 + lead_r] & 0x80) == 0x80);
int8_t lead_s = 0; // leading zeros
int8_t lead_r = 0;
for (i=0; i < 32; i++)
if (sigbuf[i] == 0) lead_r++;
else break;
for (i=0; i < 32; i++)
if (sigbuf[i+32] == 0) lead_s++;
else break;
sigder[0] = 0x30;
sigder[1] = 0x44 + pad_s + pad_r;
sigder[1] = 0x44 + pad_s + pad_r - lead_s - lead_r;
sigder[2] = 0x02;
sigder[3 + pad_r] = 0;
sigder[3] = 0x20 + pad_r;
memmove(sigder + 4 + pad_r, sigbuf, 32);
sigder[3] = 0x20 + pad_r - lead_r;
memmove(sigder + 4 + pad_r, sigbuf + lead_r, 32);
sigder[4 + 32 + pad_r] = 0x02;
sigder[5 + 32 + pad_r + pad_s] = 0;
sigder[5 + 32 + pad_r] = 0x20 + pad_s;
memmove(sigder + 6 + 32 + pad_r + pad_s, sigbuf + 32, 32);
sigder[4 + 32 + pad_r - lead_r] = 0x02;
sigder[5 + 32 + pad_r + pad_s - lead_r] = 0;
sigder[5 + 32 + pad_r - lead_r] = 0x20 + pad_s - lead_s;
memmove(sigder + 6 + 32 + pad_r + pad_s - lead_r, sigbuf + 32 + lead_s, 32);
//
return 0x46 + pad_s + pad_r;
return 0x46 + pad_s + pad_r - lead_r - lead_s;
}
uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
@ -415,12 +427,29 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
check_ret(ret);
}
// Return 1 if credential belongs to this token
int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc)
{
uint8_t tag[16];
if (desc->type != PUB_KEY_CRED_PUB_KEY)
{
printf1(TAG_GA,"unsupported credential type: %d\n", desc->type);
return 0;
}
make_auth_tag(rp, &desc->credential.fields.user, desc->credential.fields.count, tag);
return (memcmp(desc->credential.fields.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
}
uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
{
CTAP_makeCredential MC;
int ret;
int ret, i;
uint8_t auth_data_buf[300];
CTAP_credentialDescriptor * excl_cred = (CTAP_credentialDescriptor *) auth_data_buf;
uint8_t * hashbuf = auth_data_buf + 0;
uint8_t * sigbuf = auth_data_buf + 32;
uint8_t * sigder = auth_data_buf + 32 + 64;
@ -451,6 +480,20 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
}
}
for (i = 0; i < MC.excludeListSize; i++)
{
ret = parse_credential_descriptor(&MC.excludeList, excl_cred);
check_retr(ret);
if (ctap_authenticate_credential(&MC.rp, excl_cred))
{
return CTAP2_ERR_CREDENTIAL_EXCLUDED;
}
ret = cbor_value_advance(&MC.excludeList);
check_ret(ret);
}
CborEncoder map;
ret = cbor_encoder_create_map(encoder, &map, 3);
check_ret(ret);
@ -478,22 +521,6 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
return CTAP1_ERR_SUCCESS;
}
// Return 1 if credential belongs to this token
int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc)
{
uint8_t tag[16];
if (desc->type != PUB_KEY_CRED_PUB_KEY)
{
printf1(TAG_GA,"unsupported credential type: %d\n", desc->type);
return 0;
}
make_auth_tag(rp, &desc->credential.fields.user, desc->credential.fields.count, tag);
return (memcmp(desc->credential.fields.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
}
static int pick_first_authentic_credential(CTAP_getAssertion * GA)
{
int i;

5
ctap.h
View File

@ -1,6 +1,8 @@
#ifndef _CTAP_H
#define _CTAP_H
#include "cbor.h"
#define CTAP_MAKE_CREDENTIAL 0x01
#define CTAP_GET_ASSERTION 0x02
#define CTAP_CANCEL 0x03
@ -162,6 +164,9 @@ typedef struct
uint8_t publicKeyCredentialType;
int32_t COSEAlgorithmIdentifier;
CborValue excludeList;
int excludeListSize;
uint8_t rk;
uint8_t uv;

View File

@ -10,6 +10,7 @@
#include "util.h"
#include "usbhid.h"
#include "log.h"
void ctaphid_write_block(uint8_t * data)
@ -34,15 +35,16 @@ uint32_t ctap_atomic_count(int sel)
{
static uint32_t counter1 = 25;
static uint32_t counter2 = 25;
/*return 713;*/
if (sel == 0)
{
printf1(TAG_RED,"counter1: %d\n", counter1);
return counter1++;
}
else
{
return counter2++;
}
return 44;
}
int ctap_generate_rng(uint8_t * dst, size_t num)
@ -55,6 +57,9 @@ int ctap_generate_rng(uint8_t * dst, size_t num)
}
fread(dst, 1, num, urand);
fclose(urand);
/*memset(dst,0xaa,num);*/
return 1;
}

View File

@ -556,6 +556,18 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
break;
case MC_excludeList:
printf1(TAG_MC,"CTAP_excludeList\n");
if( cbor_value_get_type(&map) == CborArrayType )
{
ret = cbor_value_enter_container(&map, &MC->excludeList);
check_ret(ret);
ret = cbor_value_get_int_checked(&map, &MC->excludeListSize);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case MC_extensions:
printf1(TAG_MC,"CTAP_extensions\n");
@ -604,12 +616,68 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
return 0;
}
uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cred)
{
int ret;
size_t buflen;
uint8_t type[12];
CborValue val;
if (cbor_value_get_type(arr) != CborMapType)
{
printf2(TAG_ERR,"Error, CborMapType expected in allow_list\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_map_find_value(arr, "id", &val);
check_ret(ret);
if (cbor_value_get_type(&val) != CborByteStringType)
{
printf2(TAG_ERR,"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, cred->credential.id, &buflen, NULL);
if (buflen != CREDENTIAL_ID_SIZE)
{
printf2(TAG_ERR,"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);
check_ret(ret);
if (cbor_value_get_type(&val) != CborTextStringType)
{
printf2(TAG_ERR,"Error, No valid type field\n");
return CTAP2_ERR_MISSING_PARAMETER;
}
buflen = sizeof(type);
cbor_value_copy_text_string(&val, type, &buflen, NULL);
if (strcmp(type, "public-key") == 0)
{
cred->type = PUB_KEY_CRED_PUB_KEY;
}
else
{
cred->type = PUB_KEY_CRED_UNKNOWN;
}
ret = cbor_value_advance(arr);
check_ret(ret);
return 0;
}
uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
{
CborValue arr, val;
size_t len,buflen;
uint8_t type[12];
CborValue arr;
size_t len;
int i,ret;
CTAP_credentialDescriptor * cred;
if (cbor_value_get_type(it) != CborArrayType)
{
@ -634,53 +702,10 @@ uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
}
GA->credLen += 1;
cred = &GA->creds[i];
if (cbor_value_get_type(&arr) != CborMapType)
{
printf2(TAG_ERR,"Error, CborMapType expected in allow_list\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_map_find_value(&arr, "id", &val);
check_ret(ret);
if (cbor_value_get_type(&val) != CborByteStringType)
{
printf2(TAG_ERR,"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)
{
printf2(TAG_ERR,"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);
check_ret(ret);
if (cbor_value_get_type(&val) != CborTextStringType)
{
printf2(TAG_ERR,"Error, No valid type field\n");
return CTAP2_ERR_MISSING_PARAMETER;
}
buflen = sizeof(type);
cbor_value_copy_text_string(&val, type, &buflen, NULL);
if (strcmp(type, "public-key") == 0)
{
GA->creds[i].type = PUB_KEY_CRED_PUB_KEY;
}
else
{
GA->creds[i].type = PUB_KEY_CRED_UNKNOWN;
}
ret = cbor_value_advance(&arr);
check_ret(ret);
ret = parse_credential_descriptor(&arr,cred);
check_retr(ret);
}
return 0;
}

View File

@ -30,6 +30,7 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length);
uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int length);
uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length);
uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cred);
#endif