diff --git a/pico-keys-sdk b/pico-keys-sdk index 38f0e2c..fa62921 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 38f0e2cc3a783674f9e4951ffc11d9520601407e +Subproject commit fa6292118d32990be0bcfc8cb60bbbecaa99b57a diff --git a/src/fido/cbor.c b/src/fido/cbor.c index c1ee944..e70e355 100644 --- a/src/fido/cbor.c +++ b/src/fido/cbor.c @@ -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 diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c index 4c8a3a9..1988e6f 100644 --- a/src/fido/cbor_client_pin.c +++ b/src/fido/cbor_client_pin.c @@ -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); diff --git a/src/fido/cbor_config.c b/src/fido/cbor_config.c index 4886bc0..e17124d 100644 --- a/src/fido/cbor_config.c +++ b/src/fido/cbor_config.c @@ -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); diff --git a/src/fido/cbor_cred_mgmt.c b/src/fido/cbor_cred_mgmt.c index 16416dc..a98cd53 100644 --- a/src/fido/cbor_cred_mgmt.c +++ b/src/fido/cbor_cred_mgmt.c @@ -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); diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c index b1c8728..8d7e035 100644 --- a/src/fido/cbor_get_assertion.c +++ b/src/fido/cbor_get_assertion.c @@ -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(); diff --git a/src/fido/cbor_get_info.c b/src/fido/cbor_get_info.c index 38cbf8d..424fe4b 100644 --- a/src/fido/cbor_get_info.c +++ b/src/fido/cbor_get_info.c @@ -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; } diff --git a/src/fido/cbor_large_blobs.c b/src/fido/cbor_large_blobs.c index 9f65e37..c8e2a48 100644 --- a/src/fido/cbor_large_blobs.c +++ b/src/fido/cbor_large_blobs.c @@ -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; } diff --git a/src/fido/cbor_make_credential.c b/src/fido/cbor_make_credential.c index 176843b..cda98fb 100644 --- a/src/fido/cbor_make_credential.c +++ b/src/fido/cbor_make_credential.c @@ -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) { diff --git a/src/fido/cbor_vendor.c b/src/fido/cbor_vendor.c index 01b0bdb..e746b80 100644 --- a/src/fido/cbor_vendor.c +++ b/src/fido/cbor_vendor.c @@ -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); diff --git a/src/fido/cmd_register.c b/src/fido/cmd_register.c index 237f70f..66629ee 100644 --- a/src/fido/cmd_register.c +++ b/src/fido/cmd_register.c @@ -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; diff --git a/src/fido/fido.c b/src/fido/fido.c index 9a6ab85..63ed4f0 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -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; diff --git a/src/fido/management.c b/src/fido/management.c index 26ae35e..3c94c1c 100644 --- a/src/fido/management.c +++ b/src/fido/management.c @@ -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; } diff --git a/src/fido/oath.c b/src/fido/oath.c index 0a5d681..098bfa2 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -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; diff --git a/src/fido/otp.c b/src/fido/otp.c index 6a8fea7..1c41e99 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -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;