Adding Credential manager.

Also adding resident credentials.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2022-09-20 19:50:33 +02:00
parent 72ebb2b596
commit 8a379d9702
No known key found for this signature in database
GPG Key ID: C0095B7870A4CCD3
5 changed files with 66 additions and 11 deletions

View File

@ -220,7 +220,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
if (strcmp(excludeList[e].type.data, "public-key") != 0)
continue;
if (credential_verify(&excludeList[e].id, rp_id_hash) == 0)
if (credential_verify(excludeList[e].id.data, excludeList[e].id.len, rp_id_hash) == 0)
CBOR_ERROR(CTAP2_ERR_CREDENTIAL_EXCLUDED);
}
@ -235,7 +235,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
uint8_t cred_id[MAX_CRED_ID_LENGTH];
size_t cred_id_len = 0;
CBOR_ERROR(credential_create(&rp.id, &user.id, &user.parent.name, &user.displayName, hmac_secret, (!ka || ka->use_sign_count == ptrue), alg, curve, cred_id, &cred_id_len));
CBOR_CHECK(credential_create(&rp.id, &user.id, &user.parent.name, &user.displayName, hmac_secret, (!ka || ka->use_sign_count == ptrue), alg, curve, cred_id, &cred_id_len));
mbedtls_ecp_group_id mbedtls_curve = MBEDTLS_ECP_DP_SECP256R1;
if (curve == FIDO2_CURVE_P256)
@ -377,6 +377,10 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
if (options.rk == ptrue) {
if (credential_store(cred_id, cred_id_len, rp_id_hash) != 0)
CBOR_ERROR(CTAP2_ERR_KEY_STORE_FULL);
}
err:
CBOR_FREE_BYTE_STRING(clientDataHash);
CBOR_FREE_BYTE_STRING(pinUvAuthParam);

View File

@ -23,16 +23,19 @@
#include "fido.h"
#include "ctap.h"
#include "random.h"
#include "files.h"
#include "file.h"
#include "hsm.h"
int credential_verify(CborByteString *cred_id, const uint8_t *rp_id_hash) {
if (cred_id->len < 4+12+16)
int credential_verify(uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash) {
if (cred_id_len < 4+12+16)
return -1;
uint8_t key[32], *iv = cred_id->data + 4, *cipher = cred_id->data + 4 + 12, *tag = cred_id->data - 16;
uint8_t key[32], *iv = cred_id + 4, *cipher = cred_id + 4 + 12, *tag = cred_id + cred_id_len - 16;
memset(key, 0, sizeof(key));
mbedtls_chachapoly_context chatx;
mbedtls_chachapoly_init(&chatx);
mbedtls_chachapoly_setkey(&chatx, key);
return mbedtls_chachapoly_auth_decrypt(&chatx, cred_id->len - (4 + 12 + 16), iv, rp_id_hash, 32, tag, cipher, cipher);
return mbedtls_chachapoly_auth_decrypt(&chatx, cred_id_len - (4 + 12 + 16), iv, rp_id_hash, 32, tag, cipher, cipher);
}
int credential_create(CborCharString *rpId, CborByteString *userId, CborCharString *userName, CborCharString *userDisplayName, const bool *hmac_secret, bool use_sign_count, int alg, int curve, uint8_t *cred_id, size_t *cred_id_len) {
@ -40,7 +43,7 @@ int credential_create(CborCharString *rpId, CborByteString *userId, CborCharStri
CborError error = CborNoError;
uint8_t rp_id_hash[32];
mbedtls_sha256((uint8_t *)rpId->data, rpId->len, rp_id_hash, 0);
cbor_encoder_init(&encoder, cred_id+4+12, sizeof(cred_id)-(4+12+16), 0);
cbor_encoder_init(&encoder, cred_id+4+12, MAX_CRED_ID_LENGTH-(4+12+16), 0);
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, CborIndefiniteLength));
CBOR_APPEND_KEY_UINT_VAL_STRING(mapEncoder, 0x01, *rpId);
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x02));
@ -82,16 +85,18 @@ int credential_create(CborCharString *rpId, CborByteString *userId, CborCharStri
return 0;
}
int credential_load(CborByteString *cred_id, const uint8_t *rp_id_hash, Credential *cred) {
int credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, Credential *cred) {
int ret = 0;
ret = credential_verify(cred_id, rp_id_hash);
uint8_t *copy_cred_id = (uint8_t *)calloc(1, cred_id_len);
memcpy(copy_cred_id, cred_id, cred_id_len);
ret = credential_verify(copy_cred_id, cred_id_len, rp_id_hash);
if (ret != 0)
return ret;
CborParser parser;
CborValue map;
CborError error;
memset(cred, 0, sizeof(Credential));
CBOR_CHECK(cbor_parser_init(cred_id->data + 4 + 12, cred_id->len - (4 + 12 + 16), 0, &parser, &map));
CBOR_CHECK(cbor_parser_init(copy_cred_id + 4 + 12, cred_id_len - (4 + 12 + 16), 0, &parser, &map));
CBOR_PARSE_MAP_START(map, 1) {
uint64_t val_u = 0;
CBOR_FIELD_GET_UINT(val_u, 1);
@ -123,6 +128,7 @@ int credential_load(CborByteString *cred_id, const uint8_t *rp_id_hash, Credenti
cred->present = true;
err:
free(copy_cred_id);
if (error != CborNoError) {
if (error == CborErrorImproperValue)
return CTAP2_ERR_CBOR_UNEXPECTED_TYPE;
@ -135,3 +141,45 @@ void credential_free(Credential *cred) {
CBOR_FREE_BYTE_STRING(cred->rpId);
CBOR_FREE_BYTE_STRING(cred->userId);
}
int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash) {
file_t *slot = NULL;
Credential cred = {0};
int ret = 0;
ret = credential_load(cred_id, cred_id_len, rp_id_hash, &cred);
if (ret != 0) {
credential_free(&cred);
return ret;
}
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
file_t *ef = search_dynamic_file(EF_CRED + i);
Credential rcred = {0};
if (!file_has_data(ef)) {
if (slot == NULL)
slot = ef;
continue;
}
if (memcmp(file_get_data(ef), rp_id_hash, 32) != 0)
continue;
ret = credential_load(file_get_data(ef) + 32, file_get_size(ef)-32, rp_id_hash, &rcred);
if (ret != 0) {
credential_free(&rcred);
continue;
}
if (memcmp(rcred.userId.data, cred.userId.data, MIN(rcred.userId.len, cred.userId.len)) == 0) {
slot = ef;
credential_free(&rcred);
break;
}
credential_free(&rcred);
}
if (slot == NULL)
return -1;
credential_free(&cred);
uint8_t *data = (uint8_t *)calloc(1, cred_id_len+32);
memcpy(data, rp_id_hash, 32);
memcpy(data + 32, cred_id, cred_id_len);
flash_write_data_to_file(slot, data, cred_id_len + 32);
low_flash_available();
return 0;
}

View File

@ -38,8 +38,9 @@ typedef struct Credential {
bool present;
} Credential;
extern int credential_verify(CborByteString *cred_id, const uint8_t *rp_id_hash);
extern int credential_verify(uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash);
extern int credential_create(CborCharString *rpId, CborByteString *userId, CborCharString *userName, CborCharString *userDisplayName, const bool *hmac_secret, bool use_sign_count, int alg, int curve, uint8_t *cred_id, size_t *cred_id_len);
extern void credential_free(Credential *cred);
extern int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash);
#endif // _CREDENTIAL_H_

View File

@ -67,6 +67,7 @@ extern void init_fido();
extern bool getUserVerifiedFlagValue();
#define MAX_CREDENTIAL_COUNT_IN_LIST 16
#define MAX_CRED_ID_LENGTH 1024
#define MAX_RESIDENT_CREDENTIALS 256
typedef struct known_app {
const uint8_t *rp_id_hash;

View File

@ -25,6 +25,7 @@
#define EF_COUNTER 0xC000
#define EF_PIN 0x1080
#define EF_AUTHTOKEN 0x1090
#define EF_CRED 0xCF00 // Creds at 0xCF00 - 0xCFFF
extern file_t *ef_keydev;
extern file_t *ef_certdev;