Add checks to use U2F key if necessary

This commit is contained in:
Conor Patrick 2019-04-13 22:37:31 -04:00
parent 89e9296825
commit 44fa3bbb8e
5 changed files with 49 additions and 16 deletions

View File

@ -11,6 +11,7 @@
#include "cbor.h" #include "cbor.h"
#include "ctap.h" #include "ctap.h"
#include "u2f.h"
#include "ctaphid.h" #include "ctaphid.h"
#include "ctap_parse.h" #include "ctap_parse.h"
#include "ctap_errors.h" #include "ctap_errors.h"
@ -431,6 +432,12 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf
return 0; return 0;
} }
static unsigned int get_credential_id_size(CTAP_credentialDescriptor * cred)
{
if (cred->type == PUB_KEY_CRED_CTAP1)
return U2F_KEY_HANDLE_SIZE;
return sizeof(CredentialId);
}
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, uint32_t * len, CTAP_credInfo * credInfo) static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, uint32_t * len, CTAP_credInfo * credInfo)
{ {
@ -655,11 +662,25 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
// Return 1 if credential belongs to this token // Return 1 if credential belongs to this token
int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc) int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc)
{ {
uint8_t rpIdHash[32];
uint8_t tag[16]; uint8_t tag[16];
make_auth_tag(desc->credential.id.rpIdHash, desc->credential.id.nonce, desc->credential.id.count, tag); switch(desc->type)
{
case PUB_KEY_CRED_PUB_KEY:
make_auth_tag(desc->credential.id.rpIdHash, desc->credential.id.nonce, desc->credential.id.count, tag);
return (memcmp(desc->credential.id.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
break;
case PUB_KEY_CRED_CTAP1:
printf1(TAG_CTAP,"PUB_KEY_CRED_CTAP1\r\n");
crypto_sha256_init();
crypto_sha256_update(rp->id, rp->size);
crypto_sha256_final(rpIdHash);
return u2f_authenticate_credential((struct u2f_key_handle *)&desc->credential.id, rpIdHash);
break;
}
return (memcmp(desc->credential.id.tag, tag, CREDENTIAL_TAG_SIZE) == 0); return 0;
} }
@ -806,7 +827,8 @@ static uint8_t ctap_add_credential_descriptor(CborEncoder * map, CTAP_credential
ret = cbor_encode_text_string(&desc, "id", 2); ret = cbor_encode_text_string(&desc, "id", 2);
check_ret(ret); check_ret(ret);
ret = cbor_encode_byte_string(&desc, (uint8_t*)&cred->credential.id, sizeof(CredentialId)); ret = cbor_encode_byte_string(&desc, (uint8_t*)&cred->credential.id,
get_credential_id_size(cred));
check_ret(ret); check_ret(ret);
} }
@ -1021,7 +1043,8 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
check_ret(ret); check_ret(ret);
} }
crypto_ecc256_load_key((uint8_t*)&cred->credential.id, sizeof(CredentialId), NULL, 0); unsigned int cred_size = get_credential_id_size(cred);
crypto_ecc256_load_key((uint8_t*)&cred->credential.id, cred_size, NULL, 0);
#ifdef ENABLE_U2F_EXTENSIONS #ifdef ENABLE_U2F_EXTENSIONS
if ( extend_fido2(&cred->credential.id, sigder) ) if ( extend_fido2(&cred->credential.id, sigder) )
@ -1170,8 +1193,6 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
printf1(TAG_GA,"CRED ID (# %d)\n", GA.creds[j].credential.id.count); printf1(TAG_GA,"CRED ID (# %d)\n", GA.creds[j].credential.id.count);
} }
CTAP_credentialDescriptor * cred = &GA.creds[validCredCount - 1]; CTAP_credentialDescriptor * cred = &GA.creds[validCredCount - 1];
GA.extensions.hmac_secret.credential = &cred->credential; GA.extensions.hmac_secret.credential = &cred->credential;

View File

@ -112,6 +112,7 @@
#define CREDENTIAL_ENC_SIZE 176 // pad to multiple of 16 bytes #define CREDENTIAL_ENC_SIZE 176 // pad to multiple of 16 bytes
#define PUB_KEY_CRED_PUB_KEY 0x01 #define PUB_KEY_CRED_PUB_KEY 0x01
#define PUB_KEY_CRED_CTAP1 0x41
#define PUB_KEY_CRED_UNKNOWN 0x3F #define PUB_KEY_CRED_UNKNOWN 0x3F
#define CREDENTIAL_IS_SUPPORTED 1 #define CREDENTIAL_IS_SUPPORTED 1

View File

@ -9,6 +9,7 @@
#include "cbor.h" #include "cbor.h"
#include "ctap.h" #include "ctap.h"
#include "u2f.h"
#include "ctap_parse.h" #include "ctap_parse.h"
#include "ctap_errors.h" #include "ctap_errors.h"
#include "cose_key.h" #include "cose_key.h"
@ -890,10 +891,15 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
buflen = sizeof(CredentialId); buflen = sizeof(CredentialId);
cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential.id, &buflen, NULL); cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential.id, &buflen, NULL);
if (buflen != sizeof(CredentialId))
if (buflen == U2F_KEY_HANDLE_SIZE)
{
printf2(TAG_PARSE,"CTAP1 credential\n");
cred->type = PUB_KEY_CRED_CTAP1;
}
else if (buflen != sizeof(CredentialId))
{ {
printf2(TAG_ERR,"Ignoring credential is incorrect length\n"); printf2(TAG_ERR,"Ignoring 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); ret = cbor_value_map_find_value(arr, "type", &val);
@ -906,11 +912,15 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
} }
buflen = sizeof(type); buflen = sizeof(type);
cbor_value_copy_text_string(&val, type, &buflen, NULL); ret = cbor_value_copy_text_string(&val, type, &buflen, NULL);
check_ret(ret);
if (strncmp(type, "public-key",11) == 0) if (strncmp(type, "public-key",11) == 0)
{ {
cred->type = PUB_KEY_CRED_PUB_KEY; if (PUB_KEY_CRED_CTAP1 != cred->type)
{
cred->type = PUB_KEY_CRED_PUB_KEY;
}
} }
else else
{ {

View File

@ -183,21 +183,21 @@ int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pu
} }
// Return 1 if authenticate, 0 if not.
static int8_t u2f_appid_eq(struct u2f_key_handle * kh, uint8_t * appid) int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * appid)
{ {
uint8_t tag[U2F_KEY_HANDLE_TAG_SIZE]; uint8_t tag[U2F_KEY_HANDLE_TAG_SIZE];
u2f_make_auth_tag(kh, appid, tag); u2f_make_auth_tag(kh, appid, tag);
if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0) if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0)
{ {
return 0; return 1;
} }
else else
{ {
printf1(TAG_U2F, "key handle + appid not authentic\n"); printf1(TAG_U2F, "key handle + appid not authentic\n");
printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE); printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE);
printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE); printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE);
return -1; return 0;
} }
} }
@ -214,7 +214,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
if (control == U2F_AUTHENTICATE_CHECK) if (control == U2F_AUTHENTICATE_CHECK)
{ {
printf1(TAG_U2F, "CHECK-ONLY\r\n"); printf1(TAG_U2F, "CHECK-ONLY\r\n");
if (u2f_appid_eq(&req->kh, req->app) == 0) if (u2f_authenticate_credential(&req->kh, req->app))
{ {
return U2F_SW_CONDITIONS_NOT_SATISFIED; return U2F_SW_CONDITIONS_NOT_SATISFIED;
} }
@ -226,7 +226,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
if ( if (
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) || (control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
req->khl != U2F_KEY_HANDLE_SIZE || req->khl != U2F_KEY_HANDLE_SIZE ||
u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important (!u2f_authenticate_credential(&req->kh, req->app)) || // Order of checks is important
u2f_load_key(&req->kh, req->app) != 0 u2f_load_key(&req->kh, req->app) != 0
) )

View File

@ -103,6 +103,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
// @len data length // @len data length
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp); void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp);
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * appid);
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
void u2f_reset_response(); void u2f_reset_response();