fix infrequent der formatting bug. start excludelist
This commit is contained in:
parent
644ceaef63
commit
10e50bea48
83
ctap.c
83
ctap.c
@ -344,6 +344,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
|||||||
// @return length of der signature
|
// @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 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
|
// calculate attestation sig
|
||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(data, datalen);
|
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);
|
crypto_sha256_final(hashbuf);
|
||||||
|
|
||||||
printf1(TAG_GREEN, "sha256: "); dump_hex1(TAG_DUMP,hashbuf,32);
|
printf1(TAG_GREEN, "sha256: "); dump_hex1(TAG_DUMP,hashbuf,32);
|
||||||
|
|
||||||
crypto_ecc256_sign(hashbuf, 32, sigbuf);
|
crypto_ecc256_sign(hashbuf, 32, sigbuf);
|
||||||
|
|
||||||
|
|
||||||
// Need to caress into dumb der format ..
|
// Need to caress into dumb der format ..
|
||||||
uint8_t pad_s = (sigbuf[32] & 0x80) == 0x80;
|
int8_t pad_s = ((sigbuf[32 + lead_s] & 0x80) == 0x80); // Is MSBit a 1?
|
||||||
uint8_t pad_r = (sigbuf[0] & 0x80) == 0x80;
|
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[0] = 0x30;
|
||||||
sigder[1] = 0x44 + pad_s + pad_r;
|
sigder[1] = 0x44 + pad_s + pad_r - lead_s - lead_r;
|
||||||
|
|
||||||
sigder[2] = 0x02;
|
sigder[2] = 0x02;
|
||||||
sigder[3 + pad_r] = 0;
|
sigder[3 + pad_r] = 0;
|
||||||
sigder[3] = 0x20 + pad_r;
|
sigder[3] = 0x20 + pad_r - lead_r;
|
||||||
memmove(sigder + 4 + pad_r, sigbuf, 32);
|
memmove(sigder + 4 + pad_r, sigbuf + lead_r, 32);
|
||||||
|
|
||||||
sigder[4 + 32 + pad_r] = 0x02;
|
sigder[4 + 32 + pad_r - lead_r] = 0x02;
|
||||||
sigder[5 + 32 + pad_r + pad_s] = 0;
|
sigder[5 + 32 + pad_r + pad_s - lead_r] = 0;
|
||||||
sigder[5 + 32 + pad_r] = 0x20 + pad_s;
|
sigder[5 + 32 + pad_r - lead_r] = 0x20 + pad_s - lead_s;
|
||||||
memmove(sigder + 6 + 32 + pad_r + pad_s, sigbuf + 32, 32);
|
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)
|
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);
|
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)
|
uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
||||||
{
|
{
|
||||||
CTAP_makeCredential MC;
|
CTAP_makeCredential MC;
|
||||||
int ret;
|
int ret, i;
|
||||||
uint8_t auth_data_buf[300];
|
uint8_t auth_data_buf[300];
|
||||||
|
CTAP_credentialDescriptor * excl_cred = (CTAP_credentialDescriptor *) auth_data_buf;
|
||||||
uint8_t * hashbuf = auth_data_buf + 0;
|
uint8_t * hashbuf = auth_data_buf + 0;
|
||||||
uint8_t * sigbuf = auth_data_buf + 32;
|
uint8_t * sigbuf = auth_data_buf + 32;
|
||||||
uint8_t * sigder = auth_data_buf + 32 + 64;
|
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;
|
CborEncoder map;
|
||||||
ret = cbor_encoder_create_map(encoder, &map, 3);
|
ret = cbor_encoder_create_map(encoder, &map, 3);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
@ -478,22 +521,6 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
|
|||||||
return CTAP1_ERR_SUCCESS;
|
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)
|
static int pick_first_authentic_credential(CTAP_getAssertion * GA)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
5
ctap.h
5
ctap.h
@ -1,6 +1,8 @@
|
|||||||
#ifndef _CTAP_H
|
#ifndef _CTAP_H
|
||||||
#define _CTAP_H
|
#define _CTAP_H
|
||||||
|
|
||||||
|
#include "cbor.h"
|
||||||
|
|
||||||
#define CTAP_MAKE_CREDENTIAL 0x01
|
#define CTAP_MAKE_CREDENTIAL 0x01
|
||||||
#define CTAP_GET_ASSERTION 0x02
|
#define CTAP_GET_ASSERTION 0x02
|
||||||
#define CTAP_CANCEL 0x03
|
#define CTAP_CANCEL 0x03
|
||||||
@ -162,6 +164,9 @@ typedef struct
|
|||||||
uint8_t publicKeyCredentialType;
|
uint8_t publicKeyCredentialType;
|
||||||
int32_t COSEAlgorithmIdentifier;
|
int32_t COSEAlgorithmIdentifier;
|
||||||
|
|
||||||
|
CborValue excludeList;
|
||||||
|
int excludeListSize;
|
||||||
|
|
||||||
uint8_t rk;
|
uint8_t rk;
|
||||||
uint8_t uv;
|
uint8_t uv;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "usbhid.h"
|
#include "usbhid.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
void ctaphid_write_block(uint8_t * data)
|
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 counter1 = 25;
|
||||||
static uint32_t counter2 = 25;
|
static uint32_t counter2 = 25;
|
||||||
|
/*return 713;*/
|
||||||
if (sel == 0)
|
if (sel == 0)
|
||||||
{
|
{
|
||||||
|
printf1(TAG_RED,"counter1: %d\n", counter1);
|
||||||
return counter1++;
|
return counter1++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return counter2++;
|
return counter2++;
|
||||||
}
|
}
|
||||||
return 44;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ctap_generate_rng(uint8_t * dst, size_t num)
|
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);
|
fread(dst, 1, num, urand);
|
||||||
fclose(urand);
|
fclose(urand);
|
||||||
|
|
||||||
|
/*memset(dst,0xaa,num);*/
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
123
ctap_parse.c
123
ctap_parse.c
@ -556,6 +556,18 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
|
|||||||
break;
|
break;
|
||||||
case MC_excludeList:
|
case MC_excludeList:
|
||||||
printf1(TAG_MC,"CTAP_excludeList\n");
|
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;
|
break;
|
||||||
case MC_extensions:
|
case MC_extensions:
|
||||||
printf1(TAG_MC,"CTAP_extensions\n");
|
printf1(TAG_MC,"CTAP_extensions\n");
|
||||||
@ -604,12 +616,68 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
|
|||||||
return 0;
|
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)
|
uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
|
||||||
{
|
{
|
||||||
CborValue arr, val;
|
CborValue arr;
|
||||||
size_t len,buflen;
|
size_t len;
|
||||||
uint8_t type[12];
|
|
||||||
int i,ret;
|
int i,ret;
|
||||||
|
CTAP_credentialDescriptor * cred;
|
||||||
|
|
||||||
if (cbor_value_get_type(it) != CborArrayType)
|
if (cbor_value_get_type(it) != CborArrayType)
|
||||||
{
|
{
|
||||||
@ -634,53 +702,10 @@ uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GA->credLen += 1;
|
GA->credLen += 1;
|
||||||
|
cred = &GA->creds[i];
|
||||||
|
|
||||||
if (cbor_value_get_type(&arr) != CborMapType)
|
ret = parse_credential_descriptor(&arr,cred);
|
||||||
{
|
check_retr(ret);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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_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_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 ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length);
|
||||||
|
uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cred);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user