Loading credential if it belongs to U2F.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2022-09-23 11:40:39 +02:00
parent dd4b52faf3
commit 2c4c618e3b
4 changed files with 80 additions and 64 deletions

View File

@@ -52,24 +52,7 @@ int cmd_authenticate() {
return SW_EXEC_ERROR();
}
if (P1(apdu) == CTAP_AUTH_CHECK_ONLY) {
for (int i = 0; i < KEY_PATH_ENTRIES; i++) {
uint32_t k = *(uint32_t *)&req->keyHandle[i*sizeof(uint32_t)];
if (!(k & 0x80000000)) {
mbedtls_ecdsa_free(&key);
return SW_WRONG_DATA();
}
}
uint8_t hmac[32], d[32];
ret = mbedtls_ecp_write_key(&key, d, sizeof(d));
mbedtls_ecdsa_free(&key);
if (ret != 0)
return SW_WRONG_DATA();
uint8_t key_base[CTAP_APPID_SIZE + KEY_PATH_LEN];
memcpy(key_base, req->appId, CTAP_APPID_SIZE);
memcpy(key_base + CTAP_APPID_SIZE, req->keyHandle, KEY_PATH_LEN);
ret = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), d, 32, key_base, sizeof(key_base), hmac);
mbedtls_platform_zeroize(d, sizeof(d));
if (memcmp(req->keyHandle + KEY_PATH_LEN, hmac, sizeof(hmac)) != 0)
if (verify_key(req->appId, req->keyHandle, &key) != 0)
return SW_WRONG_DATA();
return SW_CONDITIONS_NOT_SATISFIED();
}

View File

@@ -104,52 +104,56 @@ int credential_create(CborCharString *rpId, CborByteString *userId, CborCharStri
int credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, Credential *cred) {
int ret = 0;
CborError error;
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));
cred->curve = FIDO2_CURVE_P256;
cred->alg = FIDO2_ALG_ES256;
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);
if (val_u == 0x01) {
CBOR_FIELD_GET_TEXT(cred->rpId, 1);
}
else if (val_u == 0x03) {
CBOR_FIELD_GET_BYTES(cred->userId, 1);
}
else if (val_u == 0x06) {
CBOR_FIELD_GET_UINT(cred->creation, 1);
}
else if (val_u == 0x07) {
cred->extensions.present = true;
CBOR_PARSE_MAP_START(_f1, 2)
{
CBOR_FIELD_GET_KEY_TEXT(2);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "hmac-secret", cred->extensions.hmac_secret);
CBOR_FIELD_KEY_TEXT_VAL_UINT(2, "credProtect", cred->extensions.credProtect);
CBOR_ADVANCE(2);
if (ret != 0) { // U2F?
if (cred_id_len != KEY_HANDLE_LEN || verify_key(rp_id_hash, cred_id, NULL) != 0)
CBOR_ERROR(CTAP2_ERR_INVALID_CREDENTIAL);
}
else {
CborParser parser;
CborValue map;
memset(cred, 0, sizeof(Credential));
cred->curve = FIDO2_CURVE_P256;
cred->alg = FIDO2_ALG_ES256;
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);
if (val_u == 0x01) {
CBOR_FIELD_GET_TEXT(cred->rpId, 1);
}
else if (val_u == 0x03) {
CBOR_FIELD_GET_BYTES(cred->userId, 1);
}
else if (val_u == 0x06) {
CBOR_FIELD_GET_UINT(cred->creation, 1);
}
else if (val_u == 0x07) {
cred->extensions.present = true;
CBOR_PARSE_MAP_START(_f1, 2)
{
CBOR_FIELD_GET_KEY_TEXT(2);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "hmac-secret", cred->extensions.hmac_secret);
CBOR_FIELD_KEY_TEXT_VAL_UINT(2, "credProtect", cred->extensions.credProtect);
CBOR_ADVANCE(2);
}
CBOR_PARSE_MAP_END(_f1, 2);
}
else if (val_u == 0x08) {
CBOR_FIELD_GET_BOOL(cred->use_sign_count, 1);
}
else if (val_u == 0x09) {
CBOR_FIELD_GET_INT(cred->alg, 1);
}
else if (val_u == 0x0A) {
CBOR_FIELD_GET_INT(cred->curve, 1);
}
else {
CBOR_ADVANCE(1);
}
CBOR_PARSE_MAP_END(_f1, 2);
}
else if (val_u == 0x08) {
CBOR_FIELD_GET_BOOL(cred->use_sign_count, 1);
}
else if (val_u == 0x09) {
CBOR_FIELD_GET_INT(cred->alg, 1);
}
else if (val_u == 0x0A) {
CBOR_FIELD_GET_INT(cred->curve, 1);
}
else {
CBOR_ADVANCE(1);
}
}
cred->id.present = true;

View File

@@ -124,6 +124,36 @@ int load_keydev(uint8_t *key) {
return CCID_OK;
}
int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_context *key) {
for (int i = 0; i < KEY_PATH_ENTRIES; i++) {
uint32_t k = *(uint32_t *)&keyHandle[i*sizeof(uint32_t)];
if (!(k & 0x80000000)) {
return -1;
}
}
mbedtls_ecdsa_context ctx;
if (key == NULL) {
mbedtls_ecdsa_init(&ctx);
key = &ctx;
if (derive_key(appId, false, (uint8_t *)keyHandle, MBEDTLS_ECP_DP_SECP256R1, &ctx) != 0) {
mbedtls_ecdsa_free(&ctx);
return -3;
}
}
uint8_t hmac[32], d[32];
int ret = mbedtls_ecp_write_key(key, d, sizeof(d));
if (key == NULL)
mbedtls_ecdsa_free(&ctx);
if (ret != 0)
return -2;
uint8_t key_base[CTAP_APPID_SIZE + KEY_PATH_LEN];
memcpy(key_base, appId, CTAP_APPID_SIZE);
memcpy(key_base + CTAP_APPID_SIZE, keyHandle, KEY_PATH_LEN);
ret = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), d, 32, key_base, sizeof(key_base), hmac);
mbedtls_platform_zeroize(d, sizeof(d));
return memcmp(keyHandle + KEY_PATH_LEN, hmac, sizeof(hmac));
}
int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int curve, mbedtls_ecdsa_context *key) {
uint8_t outk[64] = {0};
int r = 0;
@@ -131,8 +161,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
if ((r = load_keydev(outk)) != CCID_OK)
return r;
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
for (int i = 0; i < KEY_PATH_ENTRIES; i++)
{
for (int i = 0; i < KEY_PATH_ENTRIES; i++) {
if (new_key == true) {
uint32_t val = 0;
random_gen(NULL, (uint8_t *) &val, sizeof(val));
@@ -140,8 +169,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
memcpy(&key_handle[i*sizeof(uint32_t)], &val, sizeof(uint32_t));
}
r = mbedtls_hkdf(md_info, &key_handle[i * sizeof(uint32_t)], sizeof(uint32_t), outk, 32, outk + 32, 32, outk, sizeof(outk));
if (r != 0)
{
if (r != 0) {
mbedtls_platform_zeroize(outk, sizeof(outk));
return r;
}

View File

@@ -32,6 +32,7 @@
extern int scan_files(bool);
extern int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int, mbedtls_ecdsa_context *key);
extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_context *);
extern bool wait_button_pressed();
extern CTAPHID_FRAME *ctap_req, *ctap_resp;
extern void init_fido(bool);