mirror of
https://github.com/polhenarejos/pico-fido.git
synced 2024-09-20 03:10:10 +00:00
Major refactor of USB CCID and USB HID interfaces.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
parent
8c1e002892
commit
f49833291f
@ -1 +1 @@
|
||||
Subproject commit 38f0e2cc3a783674f9e4951ffc11d9520601407e
|
||||
Subproject commit fa6292118d32990be0bcfc8cb60bbbecaa99b57a
|
@ -58,7 +58,6 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
DEBUG_DATA(data + 1, len - 1);
|
||||
}
|
||||
if (cap_supported(CAP_FIDO2)) {
|
||||
driver_prepare_response_hid();
|
||||
if (cmd == CTAPHID_CBOR) {
|
||||
if (data[0] == CTAP_MAKE_CREDENTIAL) {
|
||||
return cbor_make_credential(data + 1, len - 1);
|
||||
@ -96,6 +95,7 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
}
|
||||
else if (cmd == 0xC2) {
|
||||
if (cmd_read_config() == 0x9000) {
|
||||
memmove(res_APDU-1, res_APDU, res_APDU_size);
|
||||
res_APDU_size -= 1;
|
||||
return 0;
|
||||
}
|
||||
@ -106,14 +106,12 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
|
||||
#ifndef ENABLE_EMULATION
|
||||
void cbor_thread() {
|
||||
|
||||
card_init_core1();
|
||||
while (1) {
|
||||
uint32_t m;
|
||||
queue_remove_blocking(&usb_to_card_q, &m);
|
||||
|
||||
if (m == EV_EXIT) {
|
||||
|
||||
break;
|
||||
}
|
||||
apdu.sw = cbor_parse(cmd, cbor_data, cbor_len);
|
||||
@ -140,6 +138,7 @@ int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len) {
|
||||
cbor_data = data;
|
||||
cbor_len = len;
|
||||
cmd = last_cmd;
|
||||
ctap_resp->init.data[0] = 0;
|
||||
res_APDU = ctap_resp->init.data + 1;
|
||||
res_APDU_size = 0;
|
||||
return 2; // CBOR processing
|
||||
|
@ -202,7 +202,7 @@ int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_l
|
||||
return aes_decrypt(key, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len);
|
||||
}
|
||||
else if (protocol == 2) {
|
||||
memcpy(out, in + IV_SIZE, in_len);
|
||||
memcpy(out, in + IV_SIZE, in_len - IV_SIZE);
|
||||
return aes_decrypt(key + 32, in, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len - IV_SIZE);
|
||||
}
|
||||
|
||||
@ -336,7 +336,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
}
|
||||
CBOR_PARSE_MAP_END(map, 1);
|
||||
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
if (subcommand == 0x0) {
|
||||
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
|
||||
}
|
||||
@ -516,7 +516,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
if (pin_len < minPin) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||
}
|
||||
uint8_t hsh[33];
|
||||
uint8_t hsh[34];
|
||||
hsh[0] = MAX_PIN_RETRIES;
|
||||
hsh[1] = pin_len;
|
||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, hsh + 2);
|
||||
@ -632,7 +632,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||
}
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
CBOR_FREE_BYTE_STRING(newPinEnc);
|
||||
|
@ -106,7 +106,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
}
|
||||
CBOR_PARSE_MAP_END(map, 1);
|
||||
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
|
||||
if (pinUvAuthParam.present == false) {
|
||||
CBOR_ERROR(CTAP2_ERR_PUAT_REQUIRED);
|
||||
@ -228,7 +228,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||
}
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
|
@ -120,7 +120,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
if (subcommand == 0x01) {
|
||||
if (verify(pinUvAuthProtocol, paut.data, (const uint8_t *) "\x01", 1,
|
||||
pinUvAuthParam.data) != CborNoError) {
|
||||
@ -442,7 +442,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_NO_CREDENTIALS);
|
||||
}
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
|
||||
|
@ -585,7 +585,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
if (extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) {
|
||||
lfields++;
|
||||
}
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, lfields));
|
||||
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
|
||||
@ -638,7 +638,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
}
|
||||
mbedtls_platform_zeroize(largeBlobKey, sizeof(largeBlobKey));
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
ctr++;
|
||||
file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr));
|
||||
low_flash_available();
|
||||
|
@ -26,7 +26,7 @@
|
||||
int cbor_get_info() {
|
||||
CborEncoder encoder, mapEncoder, arrayEncoder, mapEncoder2;
|
||||
CborError error = CborNoError;
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 15));
|
||||
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
|
||||
@ -133,6 +133,6 @@ err:
|
||||
if (error != CborNoError) {
|
||||
return -CTAP2_ERR_INVALID_CBOR;
|
||||
}
|
||||
res_APDU_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
res_APDU_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ int cbor_large_blobs(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
if (get > 0) {
|
||||
if (length != 0) {
|
||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||
@ -168,6 +168,6 @@ err:
|
||||
if (error != CborNoError) {
|
||||
return -CTAP2_ERR_INVALID_CBOR;
|
||||
}
|
||||
res_APDU_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
res_APDU_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder,
|
||||
extensions.largeBlobKey == ptrue &&
|
||||
options.rk == ptrue ? 5 : 4));
|
||||
@ -512,7 +512,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
}
|
||||
mbedtls_platform_zeroize(largeBlobKey, sizeof(largeBlobKey));
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
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) {
|
||||
|
@ -101,7 +101,7 @@ int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
}
|
||||
CBOR_PARSE_MAP_END(map, 1);
|
||||
|
||||
cbor_encoder_init(&encoder, res_APDU + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
|
||||
if (cmd == CTAP_VENDOR_BACKUP) {
|
||||
if (vendorCmd == 0x01) {
|
||||
@ -300,7 +300,7 @@ int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||
}
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, res_APDU + 1);
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
|
@ -32,7 +32,8 @@ const uint8_t u2f_aid[] = {
|
||||
int u2f_unload();
|
||||
int u2f_process_apdu();
|
||||
|
||||
int u2f_select(app_t *a) {
|
||||
int u2f_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_U2F)) {
|
||||
a->process_apdu = u2f_process_apdu;
|
||||
a->unload = u2f_unload;
|
||||
|
@ -61,7 +61,8 @@ uint8_t fido_get_version_minor() {
|
||||
return PICO_FIDO_VERSION_MINOR;
|
||||
}
|
||||
|
||||
int fido_select(app_t *a) {
|
||||
int fido_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_FIDO2)) {
|
||||
a->process_apdu = fido_process_apdu;
|
||||
a->unload = fido_unload;
|
||||
@ -72,11 +73,6 @@ int fido_select(app_t *a) {
|
||||
|
||||
extern uint8_t (*get_version_major)();
|
||||
extern uint8_t (*get_version_minor)();
|
||||
extern void (*init_fido_cb)();
|
||||
extern void (*cbor_thread_func)();
|
||||
extern int (*cbor_process_cb)(uint8_t, const uint8_t *, size_t);
|
||||
extern void cbor_thread();
|
||||
extern int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len);
|
||||
|
||||
INITIALIZER ( fido_ctor ) {
|
||||
#if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION)
|
||||
@ -84,11 +80,6 @@ INITIALIZER ( fido_ctor ) {
|
||||
#endif
|
||||
get_version_major = fido_get_version_major;
|
||||
get_version_minor = fido_get_version_minor;
|
||||
init_fido_cb = init_fido;
|
||||
#ifndef ENABLE_EMULATION
|
||||
cbor_thread_func = cbor_thread;
|
||||
#endif
|
||||
cbor_process_cb = cbor_process;
|
||||
register_app(fido_select, fido_aid);
|
||||
}
|
||||
|
||||
@ -224,26 +215,17 @@ int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_con
|
||||
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);
|
||||
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[67] = { 0 }; //SECP521R1 key is 66 bytes length
|
||||
int r = 0;
|
||||
memset(outk, 0, sizeof(outk));
|
||||
if ((r = load_keydev(outk)) != CCID_OK) {
|
||||
printf("Error loading keydev: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||
@ -254,15 +236,7 @@ int derive_key(const uint8_t *app_id,
|
||||
val |= 0x80000000;
|
||||
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) {
|
||||
mbedtls_platform_zeroize(outk, sizeof(outk));
|
||||
return r;
|
||||
@ -272,9 +246,7 @@ int derive_key(const uint8_t *app_id,
|
||||
uint8_t key_base[CTAP_APPID_SIZE + KEY_PATH_LEN];
|
||||
memcpy(key_base, app_id, CTAP_APPID_SIZE);
|
||||
memcpy(key_base + CTAP_APPID_SIZE, key_handle, KEY_PATH_LEN);
|
||||
if ((r =
|
||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), outk, 32, key_base,
|
||||
sizeof(key_base), key_handle + 32)) != 0) {
|
||||
if ((r = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), outk, 32, key_base, sizeof(key_base), key_handle + 32)) != 0) {
|
||||
mbedtls_platform_zeroize(outk, sizeof(outk));
|
||||
return r;
|
||||
}
|
||||
@ -337,10 +309,7 @@ int scan_files() {
|
||||
uint8_t cert[2048];
|
||||
mbedtls_ecdsa_context key;
|
||||
mbedtls_ecdsa_init(&key);
|
||||
int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1,
|
||||
&key,
|
||||
file_get_data(ef_keydev),
|
||||
file_get_size(ef_keydev));
|
||||
int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &key, file_get_data(ef_keydev), file_get_size(ef_keydev));
|
||||
if (ret != 0) {
|
||||
mbedtls_ecdsa_free(&key);
|
||||
return ret;
|
||||
@ -387,9 +356,7 @@ int scan_files() {
|
||||
}
|
||||
ef_largeblob = search_by_fid(EF_LARGEBLOB, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(ef_largeblob)) {
|
||||
file_put_data(ef_largeblob,
|
||||
(const uint8_t *) "\x80\x76\xbe\x8b\x52\x8d\x00\x75\xf7\xaa\xe9\x8d\x6f\xa5\x7a\x6d\x3c",
|
||||
17);
|
||||
file_put_data(ef_largeblob, (const uint8_t *) "\x80\x76\xbe\x8b\x52\x8d\x00\x75\xf7\xaa\xe9\x8d\x6f\xa5\x7a\x6d\x3c", 17);
|
||||
}
|
||||
low_flash_available();
|
||||
return CCID_OK;
|
||||
|
@ -32,14 +32,16 @@ const uint8_t man_aid[] = {
|
||||
};
|
||||
extern void scan_all();
|
||||
extern void init_otp();
|
||||
int man_select(app_t *a) {
|
||||
int man_select(app_t *a, uint8_t force) {
|
||||
a->process_apdu = man_process_apdu;
|
||||
a->unload = man_unload;
|
||||
sprintf((char *) res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR);
|
||||
res_APDU_size = strlen((char *) res_APDU);
|
||||
apdu.ne = res_APDU_size;
|
||||
scan_all();
|
||||
init_otp();
|
||||
if (force) {
|
||||
scan_all();
|
||||
init_otp();
|
||||
}
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,8 @@ const uint8_t oath_aid[] = {
|
||||
0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01
|
||||
};
|
||||
|
||||
int oath_select(app_t *a) {
|
||||
int oath_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_OATH)) {
|
||||
a->process_apdu = oath_process_apdu;
|
||||
a->unload = oath_unload;
|
||||
|
@ -127,7 +127,8 @@ const uint8_t otp_aid[] = {
|
||||
0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01
|
||||
};
|
||||
|
||||
int otp_select(app_t *a) {
|
||||
int otp_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_OTP)) {
|
||||
a->process_apdu = otp_process_apdu;
|
||||
a->unload = otp_unload;
|
||||
|
Loading…
Reference in New Issue
Block a user