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(); return SW_EXEC_ERROR();
} }
if (P1(apdu) == CTAP_AUTH_CHECK_ONLY) { if (P1(apdu) == CTAP_AUTH_CHECK_ONLY) {
for (int i = 0; i < KEY_PATH_ENTRIES; i++) { if (verify_key(req->appId, req->keyHandle, &key) != 0)
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)
return SW_WRONG_DATA(); return SW_WRONG_DATA();
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }

View File

@@ -104,14 +104,17 @@ 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 credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, Credential *cred) {
int ret = 0; int ret = 0;
CborError error;
uint8_t *copy_cred_id = (uint8_t *)calloc(1, cred_id_len); uint8_t *copy_cred_id = (uint8_t *)calloc(1, cred_id_len);
memcpy(copy_cred_id, cred_id, cred_id_len); memcpy(copy_cred_id, cred_id, cred_id_len);
ret = credential_verify(copy_cred_id, cred_id_len, rp_id_hash); ret = credential_verify(copy_cred_id, cred_id_len, rp_id_hash);
if (ret != 0) if (ret != 0) { // U2F?
return ret; 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; CborParser parser;
CborValue map; CborValue map;
CborError error;
memset(cred, 0, sizeof(Credential)); memset(cred, 0, sizeof(Credential));
cred->curve = FIDO2_CURVE_P256; cred->curve = FIDO2_CURVE_P256;
cred->alg = FIDO2_ALG_ES256; cred->alg = FIDO2_ALG_ES256;
@@ -152,6 +155,7 @@ int credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *r
CBOR_ADVANCE(1); CBOR_ADVANCE(1);
} }
} }
}
cred->id.present = true; cred->id.present = true;
cred->id.data = (uint8_t *)calloc(1, cred_id_len); cred->id.data = (uint8_t *)calloc(1, cred_id_len);
memcpy(cred->id.data, cred_id, cred_id_len); memcpy(cred->id.data, cred_id, cred_id_len);

View File

@@ -124,6 +124,36 @@ int load_keydev(uint8_t *key) {
return CCID_OK; 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) { 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}; uint8_t outk[64] = {0};
int r = 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) if ((r = load_keydev(outk)) != CCID_OK)
return r; return r;
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); 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) { if (new_key == true) {
uint32_t val = 0; uint32_t val = 0;
random_gen(NULL, (uint8_t *) &val, sizeof(val)); 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)); 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)); 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)); mbedtls_platform_zeroize(outk, sizeof(outk));
return r; return r;
} }

View File

@@ -32,6 +32,7 @@
extern int scan_files(bool); 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 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 bool wait_button_pressed();
extern CTAPHID_FRAME *ctap_req, *ctap_resp; extern CTAPHID_FRAME *ctap_req, *ctap_resp;
extern void init_fido(bool); extern void init_fido(bool);