refactor authData and extension handling to work for getNextAssertion

This commit is contained in:
Conor Patrick 2020-03-24 12:08:59 -04:00
parent 872a320abc
commit 3a70ee0ec6
2 changed files with 55 additions and 28 deletions

View File

@ -402,10 +402,12 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf
uint8_t shared_secret[32]; uint8_t shared_secret[32];
uint8_t hmac[32]; uint8_t hmac[32];
uint8_t credRandom[32]; uint8_t credRandom[32];
uint8_t saltEnc[64];
if (ext->hmac_secret_present == EXT_HMAC_SECRET_PARSED) if (ext->hmac_secret_present == EXT_HMAC_SECRET_PARSED)
{ {
printf1(TAG_CTAP, "Processing hmac-secret..\r\n"); printf1(TAG_CTAP, "Processing hmac-secret..\r\n");
memmove(saltEnc, ext->hmac_secret.saltEnc, sizeof(saltEnc));
crypto_ecc256_shared_secret((uint8_t*) &ext->hmac_secret.keyAgreement.pubkey, crypto_ecc256_shared_secret((uint8_t*) &ext->hmac_secret.keyAgreement.pubkey,
KEY_AGREEMENT_PRIV, KEY_AGREEMENT_PRIV,
@ -415,7 +417,7 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf
crypto_sha256_final(shared_secret); crypto_sha256_final(shared_secret);
crypto_sha256_hmac_init(shared_secret, 32, hmac); crypto_sha256_hmac_init(shared_secret, 32, hmac);
crypto_sha256_update(ext->hmac_secret.saltEnc, ext->hmac_secret.saltLen); crypto_sha256_update(saltEnc, ext->hmac_secret.saltLen);
crypto_sha256_hmac_final(shared_secret, 32, hmac); crypto_sha256_hmac_final(shared_secret, 32, hmac);
if (memcmp(ext->hmac_secret.saltAuth, hmac, 16) == 0) if (memcmp(ext->hmac_secret.saltAuth, hmac, 16) == 0)
@ -435,17 +437,17 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf
// Decrypt saltEnc // Decrypt saltEnc
crypto_aes256_init(shared_secret, NULL); crypto_aes256_init(shared_secret, NULL);
crypto_aes256_decrypt(ext->hmac_secret.saltEnc, ext->hmac_secret.saltLen); crypto_aes256_decrypt(saltEnc, ext->hmac_secret.saltLen);
// Generate outputs // Generate outputs
crypto_sha256_hmac_init(credRandom, 32, hmac_secret_output); crypto_sha256_hmac_init(credRandom, 32, hmac_secret_output);
crypto_sha256_update(ext->hmac_secret.saltEnc, 32); crypto_sha256_update(saltEnc, 32);
crypto_sha256_hmac_final(credRandom, 32, hmac_secret_output); crypto_sha256_hmac_final(credRandom, 32, hmac_secret_output);
if (ext->hmac_secret.saltLen == 64) if (ext->hmac_secret.saltLen == 64)
{ {
crypto_sha256_hmac_init(credRandom, 32, hmac_secret_output + 32); crypto_sha256_hmac_init(credRandom, 32, hmac_secret_output + 32);
crypto_sha256_update(ext->hmac_secret.saltEnc + 32, 32); crypto_sha256_update(saltEnc + 32, 32);
crypto_sha256_hmac_final(credRandom, 32, hmac_secret_output + 32); crypto_sha256_hmac_final(credRandom, 32, hmac_secret_output + 32);
} }
@ -1154,23 +1156,28 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA)
} }
static void save_credential_list(CTAP_authDataHeader * head, uint8_t * clientDataHash, CTAP_credentialDescriptor * creds, uint32_t count) static int8_t save_credential_list( uint8_t * clientDataHash,
CTAP_credentialDescriptor * creds,
uint32_t count,
CTAP_extensions * extensions)
{ {
if(count) if(count)
{ {
if (count > ALLOW_LIST_MAX_SIZE-1) if (count > ALLOW_LIST_MAX_SIZE-1)
{ {
printf2(TAG_ERR, "ALLOW_LIST_MAX_SIZE Exceeded\n"); printf2(TAG_ERR, "ALLOW_LIST_MAX_SIZE Exceeded\n");
exit(1); return CTAP2_ERR_TOO_MANY_ELEMENTS;
} }
memmove(getAssertionState.clientDataHash, clientDataHash, CLIENT_DATA_HASH_SIZE); memmove(getAssertionState.clientDataHash, clientDataHash, CLIENT_DATA_HASH_SIZE);
memmove(&getAssertionState.authData, head, sizeof(CTAP_authDataHeader));
memmove(getAssertionState.creds, creds, sizeof(CTAP_credentialDescriptor) * (count)); memmove(getAssertionState.creds, creds, sizeof(CTAP_credentialDescriptor) * (count));
memmove(&getAssertionState.extensions, extensions, sizeof(CTAP_extensions));
} }
getAssertionState.count = count; getAssertionState.count = count;
getAssertionState.index = 0; getAssertionState.index = 0;
printf1(TAG_GA,"saved %d credentials\n",count); printf1(TAG_GA,"saved %d credentials\n",count);
return 0;
} }
static CTAP_credentialDescriptor * pop_credential() static CTAP_credentialDescriptor * pop_credential()
@ -1239,8 +1246,6 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
{ {
int ret; int ret;
CborEncoder map; CborEncoder map;
CTAP_authDataHeader authData;
memmove(&authData, &getAssertionState.authData, sizeof(CTAP_authDataHeader));
CTAP_credentialDescriptor * cred = pop_credential(); CTAP_credentialDescriptor * cred = pop_credential();
@ -1249,7 +1254,7 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
return CTAP2_ERR_NOT_ALLOWED; return CTAP2_ERR_NOT_ALLOWED;
} }
auth_data_update_count(&authData); auth_data_update_count(&getAssertionState.buf.authData);
if (cred->credential.user.id_size) if (cred->credential.user.id_size)
{ {
@ -1271,7 +1276,24 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
memset(cred->credential.user.name, 0, USER_NAME_LIMIT); memset(cred->credential.user.name, 0, USER_NAME_LIMIT);
} }
ret = ctap_end_get_assertion(&map, cred, (uint8_t *)&authData, sizeof(CTAP_authDataHeader), getAssertionState.clientDataHash); uint32_t ext_encoder_buf_size = sizeof(getAssertionState.buf.extensions);
ret = ctap_make_extensions(&getAssertionState.extensions, getAssertionState.buf.extensions, &ext_encoder_buf_size);
if (ret == 0)
{
if (ext_encoder_buf_size)
{
getAssertionState.buf.authData.flags |= (1 << 7);
} else {
getAssertionState.buf.authData.flags &= ~(1 << 7);
}
}
ret = ctap_end_get_assertion(&map, cred,
(uint8_t *)&getAssertionState.buf.authData,
sizeof(CTAP_authDataHeader) + ext_encoder_buf_size,
getAssertionState.clientDataHash);
check_retr(ret); check_retr(ret);
ret = cbor_encoder_close_container(encoder, &map); ret = cbor_encoder_close_container(encoder, &map);
@ -1589,7 +1611,6 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
{ {
CTAP_getAssertion GA; CTAP_getAssertion GA;
uint8_t auth_data_buf[sizeof(CTAP_authDataHeader) + 80];
int ret = ctap_parse_get_assertion(&GA,request,length); int ret = ctap_parse_get_assertion(&GA,request,length);
if (ret != 0) if (ret != 0)
@ -1668,47 +1689,44 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
GA.extensions.hmac_secret.credential = &cred->credential; GA.extensions.hmac_secret.credential = &cred->credential;
uint32_t auth_data_buf_sz = sizeof(auth_data_buf); uint32_t auth_data_buf_sz = sizeof(CTAP_authDataHeader);
#ifdef ENABLE_U2F_EXTENSIONS #ifdef ENABLE_U2F_EXTENSIONS
if ( is_extension_request((uint8_t*)&GA.creds[0].credential.id, sizeof(CredentialId)) ) if ( is_extension_request((uint8_t*)&GA.creds[0].credential.id, sizeof(CredentialId)) )
{ {
auth_data_buf_sz = sizeof(CTAP_authDataHeader);
crypto_sha256_init(); crypto_sha256_init();
crypto_sha256_update(GA.rp.id, GA.rp.size); crypto_sha256_update(GA.rp.id, GA.rp.size);
crypto_sha256_final(((CTAP_authDataHeader *)auth_data_buf)->rpIdHash); crypto_sha256_final(getAssertionState.buf.authData.rpIdHash);
((CTAP_authDataHeader *)auth_data_buf)->flags = (1 << 0); getAssertionState.buf.authData.flags = (1 << 0);
((CTAP_authDataHeader *)auth_data_buf)->flags |= (1 << 2); getAssertionState.buf.authData.flags |= (1 << 2);
} }
else else
#endif #endif
{ {
device_disable_up(GA.up == 0); device_disable_up(GA.up == 0);
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, &auth_data_buf_sz, NULL, &GA.extensions); ret = ctap_make_auth_data(&GA.rp, &map, (uint8_t*)&getAssertionState.buf.authData, &auth_data_buf_sz, NULL, &GA.extensions);
device_disable_up(false); device_disable_up(false);
check_retr(ret); check_retr(ret);
((CTAP_authDataHeader *)auth_data_buf)->flags &= ~(1 << 2); getAssertionState.buf.authData.flags &= ~(1 << 2);
((CTAP_authDataHeader *)auth_data_buf)->flags |= (getAssertionState.user_verified << 2); getAssertionState.buf.authData.flags |= (getAssertionState.user_verified << 2);
{ {
unsigned int ext_encoder_buf_size = sizeof(auth_data_buf) - auth_data_buf_sz; unsigned int ext_encoder_buf_size = sizeof(getAssertionState.buf.extensions);
uint8_t * ext_encoder_buf = auth_data_buf + auth_data_buf_sz;
ret = ctap_make_extensions(&GA.extensions, ext_encoder_buf, &ext_encoder_buf_size); ret = ctap_make_extensions(&GA.extensions, getAssertionState.buf.extensions, &ext_encoder_buf_size);
check_retr(ret); check_retr(ret);
if (ext_encoder_buf_size) if (ext_encoder_buf_size)
{ {
((CTAP_authDataHeader *)auth_data_buf)->flags |= (1 << 7); getAssertionState.buf.authData.flags |= (1 << 7);
auth_data_buf_sz += ext_encoder_buf_size; auth_data_buf_sz += ext_encoder_buf_size;
} }
} }
} }
ret = ctap_end_get_assertion(&map, cred, auth_data_buf, auth_data_buf_sz, GA.clientDataHash); // 1,2,3,4 ret = ctap_end_get_assertion(&map, cred, (uint8_t*)&getAssertionState.buf, auth_data_buf_sz, GA.clientDataHash); // 1,2,3,4
check_retr(ret); check_retr(ret);
if (validCredCount > 1) if (validCredCount > 1)
@ -1722,7 +1740,11 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
ret = cbor_encoder_close_container(encoder, &map); ret = cbor_encoder_close_container(encoder, &map);
check_ret(ret); check_ret(ret);
save_credential_list((CTAP_authDataHeader*)auth_data_buf, GA.clientDataHash, GA.creds + 1, validCredCount - 1); // skip first one ret = save_credential_list( GA.clientDataHash,
GA.creds + 1 /* skip first credential*/,
validCredCount - 1,
&GA.extensions);
check_retr(ret);
return 0; return 0;
} }

View File

@ -336,7 +336,12 @@ typedef struct
struct _getAssertionState { struct _getAssertionState {
// Room for both authData struct and extensions
struct {
CTAP_authDataHeader authData; CTAP_authDataHeader authData;
uint8_t extensions[80];
} __attribute__((packed)) buf;
CTAP_extensions extensions;
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE]; uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE]; CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
uint8_t lastcmd; uint8_t lastcmd;