From 6c85d57412749de0aa3b78dab9f821370822775f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 18 Sep 2023 10:13:06 +0200 Subject: [PATCH 01/28] Added support for LED in Pico W. Fixed #17. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index a36a89c..10a9511 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit a36a89cc9555b9a9959218f011488c542aefc0b8 +Subproject commit 10a951135888c976369d101e36b771faab3dd469 From b1c4ff877e2402fcedc6e034b8a0d6382c02b19b Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 18 Sep 2023 10:39:21 +0200 Subject: [PATCH 02/28] Fix pico_w build. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index 10a9511..a35ba06 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit 10a951135888c976369d101e36b771faab3dd469 +Subproject commit a35ba063c4c8d04d81e794577029df8603cb5dcc From c1fd5736f90dd9bbc999a192ce1d89bee8584ee5 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 28 Oct 2023 20:51:36 +0200 Subject: [PATCH 03/28] Update to latest HSM SDK changes. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index a35ba06..4f09254 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit a35ba063c4c8d04d81e794577029df8603cb5dcc +Subproject commit 4f0925420b896c247718471da39eb9ae1f86b145 From 46ce9390bf4816b3d4132973273611ac1e77cba4 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 28 Oct 2023 20:52:07 +0200 Subject: [PATCH 04/28] Added backfall compatibility. Signed-off-by: Pol Henarejos --- src/fido/cbor.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/fido/cbor.c b/src/fido/cbor.c index f9e9269..9483d44 100644 --- a/src/fido/cbor.c +++ b/src/fido/cbor.c @@ -25,6 +25,7 @@ #include "apdu.h" #include "management.h" #include "ctap2_cbor.h" +#include "version.h" const bool _btrue = true, _bfalse = false; @@ -40,6 +41,8 @@ int cbor_config(const uint8_t *data, size_t len); int cbor_vendor(const uint8_t *data, size_t len); int cbor_large_blobs(const uint8_t *data, size_t len); +extern int cmd_read_config(); + const uint8_t aaguid[16] = { 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2") @@ -91,6 +94,12 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) { else if (cmd == CTAP_VENDOR_CBOR) { return cbor_vendor(data, len); } + else if (cmd == 0xC2) { + if (cmd_read_config() == 0x9000) { + res_APDU_size -= 1; + return 0; + } + } } return CTAP1_ERR_INVALID_CMD; } From c24be5a6319c98cc95ed410807d5c7679782cecf Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 28 Oct 2023 20:53:06 +0200 Subject: [PATCH 05/28] Adapted to new selection AID method. Signed-off-by: Pol Henarejos --- src/fido/cmd_register.c | 14 +++------ src/fido/fido.c | 22 +++++++------ src/fido/management.c | 22 ++++++------- src/fido/oath.c | 70 +++++++++++++++++++---------------------- src/fido/otp.c | 34 +++++++++----------- 5 files changed, 75 insertions(+), 87 deletions(-) diff --git a/src/fido/cmd_register.c b/src/fido/cmd_register.c index 837cb90..877f5b0 100644 --- a/src/fido/cmd_register.c +++ b/src/fido/cmd_register.c @@ -32,18 +32,14 @@ const uint8_t u2f_aid[] = { int u2f_unload(); int u2f_process_apdu(); -app_t *u2f_select(app_t *a, const uint8_t *aid, uint8_t aid_len) { - if (!memcmp(aid, u2f_aid + 1, MIN(aid_len, u2f_aid[0])) && cap_supported(CAP_U2F)) { - a->aid = u2f_aid; - a->process_apdu = u2f_process_apdu; - a->unload = u2f_unload; - return a; - } - return NULL; +int u2f_select(app_t *a) { + a->process_apdu = u2f_process_apdu; + a->unload = u2f_unload; + return CCID_OK; } void __attribute__((constructor)) u2f_ctor() { - register_app(u2f_select); + register_app(u2f_select, u2f_aid); } int u2f_unload() { diff --git a/src/fido/fido.c b/src/fido/fido.c index dc70e86..32db925 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -33,6 +33,7 @@ #include #include "management.h" #include "ctap_hid.h" +#include "version.h" int fido_process_apdu(); int fido_unload(); @@ -53,27 +54,30 @@ const uint8_t atr_fido[] = { 0x75, 0x62, 0x69, 0x4b, 0x65, 0x79, 0x40 }; -app_t *fido_select(app_t *a, const uint8_t *aid, uint8_t aid_len) { - if (!memcmp(aid, fido_aid + 1, MIN(aid_len, fido_aid[0])) && cap_supported(CAP_FIDO2)) { - a->aid = fido_aid; - a->process_apdu = fido_process_apdu; - a->unload = fido_unload; - return a; - } - return NULL; +int fido_select(app_t *a) { + a->process_apdu = fido_process_apdu; + a->unload = fido_unload; + return CCID_OK; } void __attribute__((constructor)) fido_ctor() { #if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION) ccid_atr = atr_fido; #endif - register_app(fido_select); + register_app(fido_select, fido_aid); } int fido_unload() { return CCID_OK; } +uint8_t get_version_major() { + return PICO_FIDO_VERSION_MAJOR; +} +uint8_t get_version_minor() { + return PICO_FIDO_VERSION_MINOR; +} + mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve) { if (curve == FIDO2_CURVE_P256) { return MBEDTLS_ECP_DP_SECP256R1; diff --git a/src/fido/management.c b/src/fido/management.c index f2f8df7..5d4eefb 100644 --- a/src/fido/management.c +++ b/src/fido/management.c @@ -31,22 +31,18 @@ const uint8_t man_aid[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 }; extern void scan_all(); -app_t *man_select(app_t *a, const uint8_t *aid, uint8_t aid_len) { - if (!memcmp(aid, man_aid + 1, MIN(aid_len, man_aid[0]))) { - a->aid = man_aid; - 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(); - return a; - } - return NULL; +int man_select(app_t *a) { + 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(); + return CCID_OK; } void __attribute__((constructor)) man_ctor() { - register_app(man_select); + register_app(man_select, man_aid); } int man_unload() { diff --git a/src/fido/oath.c b/src/fido/oath.c index e3d25bc..a0713c9 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -68,50 +68,46 @@ const uint8_t oath_aid[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01 }; -app_t *oath_select(app_t *a, const uint8_t *aid, uint8_t aid_len) { - if (!memcmp(aid, oath_aid + 1, MIN(aid_len, oath_aid[0])) && cap_supported(CAP_OATH)) { - a->aid = oath_aid; - a->process_apdu = oath_process_apdu; - a->unload = oath_unload; - res_APDU_size = 0; - res_APDU[res_APDU_size++] = TAG_T_VERSION; - res_APDU[res_APDU_size++] = 3; - res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR; - res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR; - res_APDU[res_APDU_size++] = 0; - res_APDU[res_APDU_size++] = TAG_NAME; - res_APDU[res_APDU_size++] = 8; +int oath_select(app_t *a) { + a->process_apdu = oath_process_apdu; + a->unload = oath_unload; + res_APDU_size = 0; + res_APDU[res_APDU_size++] = TAG_T_VERSION; + res_APDU[res_APDU_size++] = 3; + res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR; + res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR; + res_APDU[res_APDU_size++] = 0; + res_APDU[res_APDU_size++] = TAG_NAME; + res_APDU[res_APDU_size++] = 8; #ifndef ENABLE_EMULATION - pico_get_unique_board_id((pico_unique_board_id_t *) (res_APDU + res_APDU_size)); - res_APDU_size += 8; + pico_get_unique_board_id((pico_unique_board_id_t *) (res_APDU + res_APDU_size)); + res_APDU_size += 8; #else - memset(res_APDU + res_APDU_size, 0, 8); res_APDU_size += 8; + memset(res_APDU + res_APDU_size, 0, 8); res_APDU_size += 8; #endif - if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) { - random_gen(NULL, challenge, sizeof(challenge)); - res_APDU[res_APDU_size++] = TAG_CHALLENGE; - res_APDU[res_APDU_size++] = sizeof(challenge); - memcpy(res_APDU + res_APDU_size, challenge, sizeof(challenge)); - res_APDU_size += sizeof(challenge); - } - file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); - if (file_has_data(ef_otp_pin)) { - const uint8_t *pin_data = file_get_data(ef_otp_pin); - res_APDU[res_APDU_size++] = TAG_PIN_COUNTER; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = *pin_data; - } - res_APDU[res_APDU_size++] = TAG_ALGO; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; - apdu.ne = res_APDU_size; - return a; + if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) { + random_gen(NULL, challenge, sizeof(challenge)); + res_APDU[res_APDU_size++] = TAG_CHALLENGE; + res_APDU[res_APDU_size++] = sizeof(challenge); + memcpy(res_APDU + res_APDU_size, challenge, sizeof(challenge)); + res_APDU_size += sizeof(challenge); } - return NULL; + file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); + if (file_has_data(ef_otp_pin)) { + const uint8_t *pin_data = file_get_data(ef_otp_pin); + res_APDU[res_APDU_size++] = TAG_PIN_COUNTER; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = *pin_data; + } + res_APDU[res_APDU_size++] = TAG_ALGO; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; + apdu.ne = res_APDU_size; + return CCID_OK; } void __attribute__((constructor)) oath_ctor() { - register_app(oath_select); + register_app(oath_select, oath_aid); } int oath_unload() { diff --git a/src/fido/otp.c b/src/fido/otp.c index a38c287..3bfce0d 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -116,25 +116,21 @@ const uint8_t otp_aid[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01 }; -app_t *otp_select(app_t *a, const uint8_t *aid, uint8_t aid_len) { - if (!memcmp(aid, otp_aid + 1, MIN(aid_len, otp_aid[0])) && cap_supported(CAP_OTP)) { - a->aid = otp_aid; - a->process_apdu = otp_process_apdu; - a->unload = otp_unload; - if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) || - file_has_data(search_dynamic_file(EF_OTP_SLOT2))) { - config_seq = 1; - } - else { - config_seq = 0; - } - otp_status(); - memmove(res_APDU, res_APDU + 1, 6); - res_APDU_size = 6; - apdu.ne = res_APDU_size; - return a; +int otp_select(app_t *a) { + a->process_apdu = otp_process_apdu; + a->unload = otp_unload; + if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) || + file_has_data(search_dynamic_file(EF_OTP_SLOT2))) { + config_seq = 1; } - return NULL; + else { + config_seq = 0; + } + otp_status(); + memmove(res_APDU, res_APDU + 1, 6); + res_APDU_size = 6; + apdu.ne = res_APDU_size; + return CCID_OK; } uint8_t modhex_tab[] = @@ -308,7 +304,7 @@ int otp_button_pressed(uint8_t slot) { } void __attribute__((constructor)) otp_ctor() { - register_app(otp_select); + register_app(otp_select, otp_aid); button_pressed_cb = otp_button_pressed; } From da94a824877b46c2e4cc5c63a9375269a156075b Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 28 Oct 2023 20:57:53 +0200 Subject: [PATCH 06/28] Fix AID selection. Signed-off-by: Pol Henarejos --- src/fido/cmd_register.c | 9 ++++-- src/fido/fido.c | 9 ++++-- src/fido/oath.c | 63 +++++++++++++++++++++-------------------- src/fido/otp.c | 29 ++++++++++--------- 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/fido/cmd_register.c b/src/fido/cmd_register.c index 877f5b0..1be7e55 100644 --- a/src/fido/cmd_register.c +++ b/src/fido/cmd_register.c @@ -33,9 +33,12 @@ int u2f_unload(); int u2f_process_apdu(); int u2f_select(app_t *a) { - a->process_apdu = u2f_process_apdu; - a->unload = u2f_unload; - return CCID_OK; + if (cap_supported(CAP_U2F)) { + a->process_apdu = u2f_process_apdu; + a->unload = u2f_unload; + return CCID_OK; + } + return CCID_ERR_FILE_NOT_FOUND; } void __attribute__((constructor)) u2f_ctor() { diff --git a/src/fido/fido.c b/src/fido/fido.c index 32db925..4431136 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -55,9 +55,12 @@ const uint8_t atr_fido[] = { }; int fido_select(app_t *a) { - a->process_apdu = fido_process_apdu; - a->unload = fido_unload; - return CCID_OK; + if (cap_supported(CAP_FIDO2)) { + a->process_apdu = fido_process_apdu; + a->unload = fido_unload; + return CCID_OK; + } + return CCID_ERR_FILE_NOT_FOUND; } void __attribute__((constructor)) fido_ctor() { diff --git a/src/fido/oath.c b/src/fido/oath.c index a0713c9..0a9b9a3 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -69,41 +69,44 @@ const uint8_t oath_aid[] = { }; int oath_select(app_t *a) { - a->process_apdu = oath_process_apdu; - a->unload = oath_unload; - res_APDU_size = 0; - res_APDU[res_APDU_size++] = TAG_T_VERSION; - res_APDU[res_APDU_size++] = 3; - res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR; - res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR; - res_APDU[res_APDU_size++] = 0; - res_APDU[res_APDU_size++] = TAG_NAME; - res_APDU[res_APDU_size++] = 8; + if (cap_supported(CAP_OATH)) { + a->process_apdu = oath_process_apdu; + a->unload = oath_unload; + res_APDU_size = 0; + res_APDU[res_APDU_size++] = TAG_T_VERSION; + res_APDU[res_APDU_size++] = 3; + res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR; + res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR; + res_APDU[res_APDU_size++] = 0; + res_APDU[res_APDU_size++] = TAG_NAME; + res_APDU[res_APDU_size++] = 8; #ifndef ENABLE_EMULATION - pico_get_unique_board_id((pico_unique_board_id_t *) (res_APDU + res_APDU_size)); - res_APDU_size += 8; + pico_get_unique_board_id((pico_unique_board_id_t *) (res_APDU + res_APDU_size)); + res_APDU_size += 8; #else - memset(res_APDU + res_APDU_size, 0, 8); res_APDU_size += 8; + memset(res_APDU + res_APDU_size, 0, 8); res_APDU_size += 8; #endif - if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) { - random_gen(NULL, challenge, sizeof(challenge)); - res_APDU[res_APDU_size++] = TAG_CHALLENGE; - res_APDU[res_APDU_size++] = sizeof(challenge); - memcpy(res_APDU + res_APDU_size, challenge, sizeof(challenge)); - res_APDU_size += sizeof(challenge); - } - file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); - if (file_has_data(ef_otp_pin)) { - const uint8_t *pin_data = file_get_data(ef_otp_pin); - res_APDU[res_APDU_size++] = TAG_PIN_COUNTER; + if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) { + random_gen(NULL, challenge, sizeof(challenge)); + res_APDU[res_APDU_size++] = TAG_CHALLENGE; + res_APDU[res_APDU_size++] = sizeof(challenge); + memcpy(res_APDU + res_APDU_size, challenge, sizeof(challenge)); + res_APDU_size += sizeof(challenge); + } + file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); + if (file_has_data(ef_otp_pin)) { + const uint8_t *pin_data = file_get_data(ef_otp_pin); + res_APDU[res_APDU_size++] = TAG_PIN_COUNTER; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = *pin_data; + } + res_APDU[res_APDU_size++] = TAG_ALGO; res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = *pin_data; + res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; + apdu.ne = res_APDU_size; + return CCID_OK; } - res_APDU[res_APDU_size++] = TAG_ALGO; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; - apdu.ne = res_APDU_size; - return CCID_OK; + return CCID_ERR_FILE_NOT_FOUND; } void __attribute__((constructor)) oath_ctor() { diff --git a/src/fido/otp.c b/src/fido/otp.c index 3bfce0d..7a8bfd3 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -117,20 +117,23 @@ const uint8_t otp_aid[] = { }; int otp_select(app_t *a) { - a->process_apdu = otp_process_apdu; - a->unload = otp_unload; - if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) || - file_has_data(search_dynamic_file(EF_OTP_SLOT2))) { - config_seq = 1; + if (cap_supported(CAP_OTP)) { + a->process_apdu = otp_process_apdu; + a->unload = otp_unload; + if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) || + file_has_data(search_dynamic_file(EF_OTP_SLOT2))) { + config_seq = 1; + } + else { + config_seq = 0; + } + otp_status(); + memmove(res_APDU, res_APDU + 1, 6); + res_APDU_size = 6; + apdu.ne = res_APDU_size; + return CCID_OK; } - else { - config_seq = 0; - } - otp_status(); - memmove(res_APDU, res_APDU + 1, 6); - res_APDU_size = 6; - apdu.ne = res_APDU_size; - return CCID_OK; + return CCID_ERR_FILE_NOT_FOUND; } uint8_t modhex_tab[] = From 7bf26b28fcf14621f1613fb53734eadc10b4b89f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 30 Oct 2023 16:51:56 +0100 Subject: [PATCH 07/28] Fixed potential memory leak. Signed-off-by: Pol Henarejos --- src/fido/oath.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fido/oath.c b/src/fido/oath.c index 0a9b9a3..d2615c7 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -454,6 +454,7 @@ int cmd_calculate_all() { if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) { return SW_INCORRECT_PARAMS(); } + res_APDU_size = 0; for (int i = 0; i < MAX_OATH_CRED; i++) { file_t *ef = search_dynamic_file(EF_OATH_CRED + i); if (file_has_data(ef)) { From 0fd36806cced45b11c1ed36c14fc505cd8d3d171 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 31 Oct 2023 00:40:56 +0100 Subject: [PATCH 08/28] Fixed potential crash. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index 4f09254..3182d1e 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit 4f0925420b896c247718471da39eb9ae1f86b145 +Subproject commit 3182d1e2e66f860f3b8f50fc2d86b4903b4f3784 From e5d1ef29a4335cd3fd483216772527cd16f32a8a Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 31 Oct 2023 17:35:59 +0100 Subject: [PATCH 09/28] Fixed OTP read packet through HID interfaces. Fixes #19. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index 3182d1e..d580194 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit 3182d1e2e66f860f3b8f50fc2d86b4903b4f3784 +Subproject commit d58019403007d18ba10c0f490f0338747d577500 From 365236854223394933dc213e011888be595bbe14 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 2 Nov 2023 09:32:19 +0100 Subject: [PATCH 10/28] Added Windows & Linux backend for backup/restore. Fixes #21 Signed-off-by: Pol Henarejos --- tools/pico-fido-tool.py | 32 +++++++++++++++++++-------- tools/secure_key/windows.py | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 tools/secure_key/windows.py diff --git a/tools/pico-fido-tool.py b/tools/pico-fido-tool.py index 9971387..4123233 100644 --- a/tools/pico-fido-tool.py +++ b/tools/pico-fido-tool.py @@ -23,7 +23,6 @@ import sys import argparse import platform from binascii import hexlify -from words import words from threading import Event from typing import Mapping, Any, Optional, Callable import struct @@ -58,14 +57,6 @@ except: from enum import IntEnum from binascii import hexlify -if (platform.system() == 'Windows' or platform.system() == 'Linux'): - from secure_key import windows as skey -elif (platform.system() == 'Darwin'): - from secure_key import macos as skey -else: - print('ERROR: platform not supported') - sys.exit(-1) - def get_pki_data(url, data=None, method='GET'): user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; ' 'rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7' @@ -252,6 +243,14 @@ class Vendor: return self.ctap.vendor(cmd, sub_cmd, params, pin_uv_protocol, pin_uv_param) def backup_save(self, filename): + if (platform.system() == 'Windows' or platform.system() == 'Linux'): + from secure_key import windows as skey + elif (platform.system() == 'Darwin'): + from secure_key import macos as skey + else: + print('ERROR: platform not supported') + sys.exit(-1) + from words import words ret = self._call( Vendor.CMD.VENDOR_BACKUP, Vendor.SUBCMD.ENABLE, @@ -270,6 +269,14 @@ class Vendor: print(f'{(c+1):02d} - {words[coef]}') def backup_load(self, filename): + if (platform.system() == 'Windows' or platform.system() == 'Linux'): + from secure_key import windows as skey + elif (platform.system() == 'Darwin'): + from secure_key import macos as skey + else: + print('ERROR: platform not supported') + sys.exit(-1) + from words import words d = 0 if (d == 0): for c in range(24): @@ -349,6 +356,13 @@ class Vendor: ) def _get_key_device(self): + if (platform.system() == 'Windows' or platform.system() == 'Linux'): + from secure_key import windows as skey + elif (platform.system() == 'Darwin'): + from secure_key import macos as skey + else: + print('ERROR: platform not supported') + sys.exit(-1) return skey.get_secure_key() def get_skey(self): diff --git a/tools/secure_key/windows.py b/tools/secure_key/windows.py new file mode 100644 index 0000000..d1c5845 --- /dev/null +++ b/tools/secure_key/windows.py @@ -0,0 +1,44 @@ +import sys +import os +import base64 + +DOMAIN = "PicoKeys.com" +USERNAME = "Pico-Fido" + +try: + import keyring +except: + print('ERROR: keyring module not found! Install keyring package.\nTry with `pip install keyring`') + sys.exit(-1) + +try: + from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption, load_pem_private_key + from cryptography.hazmat.primitives.asymmetric import ec +except: + print('ERROR: cryptography module not found! Install cryptography package.\nTry with `pip install cryptography`') + sys.exit(-1) + + + +def generate_secure_key(): + pkey = ec.generate_private_key(ec.SECP256R1()) + set_secure_key(pkey) + return keyring.get_password(DOMAIN, USERNAME) + +def get_d(key): + return load_pem_private_key(key, password=None).private_numbers().private_value.to_bytes(32, 'big') + +def set_secure_key(pk): + try: + keyring.delete_password(DOMAIN, USERNAME) + except: + pass + keyring.set_password(DOMAIN, USERNAME, pk.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()).decode()) + +def get_secure_key(): + key = None + try: + key = keyring.get_password(DOMAIN, USERNAME) + except keyring.errors.KeyringError: + key = generate_secure_key() + return get_d(key.encode()) From 8e36b4c379eebbbe25014855f9006c487fec99ec Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 2 Nov 2023 22:08:49 +0100 Subject: [PATCH 11/28] Added support for --pin flag. It loads Vendor/Ctap2Vendor with uv_token based on provided --pin. Signed-off-by: Pol Henarejos --- tools/pico-fido-tool.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/pico-fido-tool.py b/tools/pico-fido-tool.py index 4123233..38336d0 100644 --- a/tools/pico-fido-tool.py +++ b/tools/pico-fido-tool.py @@ -32,7 +32,7 @@ from enum import IntEnum, unique try: from fido2.ctap2.config import Config - from fido2.ctap2 import Ctap2 + from fido2.ctap2 import Ctap2, ClientPin, PinProtocolV2 from fido2.hid import CtapHidDevice, CTAPHID from fido2.utils import bytes2int, int2bytes from fido2 import cbor @@ -221,7 +221,7 @@ class Vendor: self.__key_enc = None self.__iv = None - self.vcfg = VendorConfig(ctap) + self.vcfg = VendorConfig(ctap, pin_uv_protocol=pin_uv_protocol, pin_uv_token=pin_uv_token) def _call(self, cmd, sub_cmd, params=None): if params: @@ -395,6 +395,7 @@ class Vendor: def parse_args(): parser = argparse.ArgumentParser() subparser = parser.add_subparsers(title="commands", dest="command") + parser.add_argument('-p','--pin', help='Specify the PIN of the device.', required=True) parser_secure = subparser.add_parser('secure', help='Manages security of Pico Fido.') parser_secure.add_argument('subcommand', choices=['enable', 'disable', 'unlock'], help='Enables, disables or unlocks the security.') @@ -440,15 +441,17 @@ def attestation(vdr, args): vdr.upload_ea(cert.public_bytes(Encoding.DER)) def main(args): - print('Pico Fido Tool v1.4') + print('Pico Fido Tool v1.5') print('Author: Pol Henarejos') print('Report bugs to https://github.com/polhenarejos/pico-fido/issues') print('') print('') dev = next(CtapHidDevice.list_devices(), None) - - vdr = Vendor(Ctap2Vendor(dev)) + ctap = Ctap2Vendor(dev) + client_pin = ClientPin(ctap) + token = client_pin.get_pin_token(args.pin) + vdr = Vendor(ctap, pin_uv_protocol=PinProtocolV2(), pin_uv_token=token) if (args.command == 'secure'): secure(vdr, args) From 65039c0959fd13b7d4e22f4fba89f553b64bbbbc Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 2 Nov 2023 22:13:45 +0100 Subject: [PATCH 12/28] Fixed AUT permission. Signed-off-by: Pol Henarejos --- tools/pico-fido-tool.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pico-fido-tool.py b/tools/pico-fido-tool.py index 38336d0..5b58911 100644 --- a/tools/pico-fido-tool.py +++ b/tools/pico-fido-tool.py @@ -90,7 +90,7 @@ class VendorConfig(Config): def enable_device_aut(self, ct): self._call( - Config.CMD.VENDOR_PROTOTYPE, + Config.CMD.CONFIG_VENDOR_PROTOTYPE, { VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_ENABLE, VendorConfig.PARAM.VENDOR_AUT_CT: ct @@ -99,7 +99,7 @@ class VendorConfig(Config): def disable_device_aut(self): self._call( - Config.CMD.VENDOR_PROTOTYPE, + Config.CMD.CONFIG_VENDOR_PROTOTYPE, { VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_DISABLE }, @@ -450,7 +450,7 @@ def main(args): dev = next(CtapHidDevice.list_devices(), None) ctap = Ctap2Vendor(dev) client_pin = ClientPin(ctap) - token = client_pin.get_pin_token(args.pin) + token = client_pin.get_pin_token(args.pin, permissions=ClientPin.PERMISSION.AUTHENTICATOR_CFG) vdr = Vendor(ctap, pin_uv_protocol=PinProtocolV2(), pin_uv_token=token) if (args.command == 'secure'): From 421bea642167b16ee09e6efd3ab18820eeee2504 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 2 Nov 2023 22:14:42 +0100 Subject: [PATCH 13/28] python-fido2 has a bug which does not allow to use 0xff as ConfigVendorPrototype. It encodes an uint8_t to int8_t and thus, the command must be <= 0x7f. Fixes #22. Signed-off-by: Pol Henarejos --- src/fido/cbor_config.c | 4 ++-- tools/pico-fido-tool.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/fido/cbor_config.c b/src/fido/cbor_config.c index 88562d8..0d6aeb8 100644 --- a/src/fido/cbor_config.c +++ b/src/fido/cbor_config.c @@ -64,7 +64,7 @@ int cbor_config(const uint8_t *data, size_t len) { raw_subpara = (uint8_t *) cbor_value_get_next_byte(&_f1); CBOR_PARSE_MAP_START(_f1, 2) { - if (subcommand == 0xff) { + if (subcommand == 0x7f) { CBOR_FIELD_GET_UINT(subpara, 2); if (subpara == 0x01) { CBOR_FIELD_GET_UINT(vendorCommandId, 2); @@ -134,7 +134,7 @@ int cbor_config(const uint8_t *data, size_t len) { CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); } - if (subcommand == 0xff) { + if (subcommand == 0x7f) { if (vendorCommandId == CTAP_CONFIG_AUT_DISABLE) { if (!file_has_data(ef_keydev_enc)) { CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED); diff --git a/tools/pico-fido-tool.py b/tools/pico-fido-tool.py index 5b58911..a12bce1 100644 --- a/tools/pico-fido-tool.py +++ b/tools/pico-fido-tool.py @@ -81,6 +81,7 @@ class VendorConfig(Config): class CMD(IntEnum): CONFIG_AUT_ENABLE = 0x03e43f56b34285e2 CONFIG_AUT_DISABLE = 0x1831a40f04a25ed9 + CONFIG_VENDOR_PROTOTYPE = 0x7f class RESP(IntEnum): KEY_AGREEMENT = 0x01 @@ -90,7 +91,7 @@ class VendorConfig(Config): def enable_device_aut(self, ct): self._call( - Config.CMD.CONFIG_VENDOR_PROTOTYPE, + VendorConfig.CMD.CONFIG_VENDOR_PROTOTYPE, { VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_ENABLE, VendorConfig.PARAM.VENDOR_AUT_CT: ct @@ -99,7 +100,7 @@ class VendorConfig(Config): def disable_device_aut(self): self._call( - Config.CMD.CONFIG_VENDOR_PROTOTYPE, + VendorConfig.CMD.CONFIG_VENDOR_PROTOTYPE, { VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_DISABLE }, From 5db1014850aa60921db489117eba8ccfcba43aac Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 11:48:32 +0100 Subject: [PATCH 14/28] Generate a secure key if it is not found. Should fix #23. Signed-off-by: Pol Henarejos --- tools/pico-fido-tool.py | 2 +- tools/secure_key/macos.py | 4 +++- tools/secure_key/windows.py | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/pico-fido-tool.py b/tools/pico-fido-tool.py index a12bce1..89d1615 100644 --- a/tools/pico-fido-tool.py +++ b/tools/pico-fido-tool.py @@ -442,7 +442,7 @@ def attestation(vdr, args): vdr.upload_ea(cert.public_bytes(Encoding.DER)) def main(args): - print('Pico Fido Tool v1.5') + print('Pico Fido Tool v1.6') print('Author: Pol Henarejos') print('Report bugs to https://github.com/polhenarejos/pico-fido/issues') print('') diff --git a/tools/secure_key/macos.py b/tools/secure_key/macos.py index 381ee21..1ccc1a4 100644 --- a/tools/secure_key/macos.py +++ b/tools/secure_key/macos.py @@ -51,7 +51,9 @@ def get_secure_key(): try: backend = get_backend(False) key = backend.get_password(DOMAIN, USERNAME)[0] - except keyring.errors.KeyringError: + if (key is None): + raise TypeError + except (keyring.errors.KeyringError, TypeError): try: key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault except keyring.errors.PasswordSetError: diff --git a/tools/secure_key/windows.py b/tools/secure_key/windows.py index d1c5845..844190a 100644 --- a/tools/secure_key/windows.py +++ b/tools/secure_key/windows.py @@ -1,6 +1,4 @@ import sys -import os -import base64 DOMAIN = "PicoKeys.com" USERNAME = "Pico-Fido" @@ -39,6 +37,8 @@ def get_secure_key(): key = None try: key = keyring.get_password(DOMAIN, USERNAME) - except keyring.errors.KeyringError: + if (key is None): + raise TypeError + except (keyring.errors.KeyringError, TypeError): key = generate_secure_key() return get_d(key.encode()) From cb2744cab37bc845de9333434b6fcb618ba521e1 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 11:49:18 +0100 Subject: [PATCH 15/28] Move some OTP functions from HID to OTP. Signed-off-by: Pol Henarejos --- src/fido/otp.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/src/fido/otp.c b/src/fido/otp.c index 7a8bfd3..65f4bdb 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -111,6 +111,13 @@ uint16_t otp_status(); int otp_process_apdu(); int otp_unload(); +#ifndef ENABLE_EMULATION +extern int (*hid_set_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t); +extern uint16_t (*hid_get_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t); +int otp_hid_set_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t); +uint16_t otp_hid_get_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t); +#endif + const uint8_t otp_aid[] = { 7, 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01 @@ -168,6 +175,10 @@ void init_otp() { } scanned = true; low_flash_available(); +#ifndef ENABLE_EMULATION + hid_set_report_cb = otp_hid_set_report_cb; + hid_get_report_cb = otp_hid_get_report_cb; +#endif } } extern int calculate_oath(uint8_t truncate, @@ -175,6 +186,22 @@ extern int calculate_oath(uint8_t truncate, size_t key_len, const uint8_t *chal, size_t chal_len); + +uint16_t calculate_crc(const uint8_t *data, size_t data_len) { + uint16_t crc = 0xFFFF; + for (size_t idx = 0; idx < data_len; idx++) { + crc ^= data[idx]; + for (uint8_t i = 0; i < 8; i++) { + uint16_t j = crc & 0x1; + crc >>= 1; + if (j == 1) { + crc ^= 0x8408; + } + } + } + return crc & 0xFFFF; +} + #ifndef ENABLE_EMULATION static uint8_t session_counter[2] = { 0 }; #endif @@ -488,3 +515,112 @@ int otp_process_apdu() { } return SW_INS_NOT_SUPPORTED(); } + +#ifndef ENABLE_EMULATION + +uint8_t otp_frame_rx[70] = {0}; +uint8_t otp_frame_tx[70] = {0}; +uint8_t otp_exp_seq = 0, otp_curr_seq = 0; +uint8_t otp_header[4] = {0}; + +extern uint16_t *get_send_buffer_size(uint8_t itf); + +int otp_send_frame(uint8_t *frame, size_t frame_len) { + uint16_t crc = calculate_crc(frame, frame_len); + frame[frame_len] = ~crc & 0xff; + frame[frame_len + 1] = ~crc >> 8; + frame_len += 2; + *get_send_buffer_size(ITF_KEYBOARD) = frame_len; + otp_exp_seq = (frame_len / 7); + if (frame_len % 7) { + otp_exp_seq++; + } + otp_curr_seq = 0; + return 0; +} + +int otp_hid_set_report_cb(uint8_t itf, + uint8_t report_id, + hid_report_type_t report_type, + uint8_t const *buffer, + uint16_t bufsize) +{ + if (report_type == 3) { + DEBUG_PAYLOAD(buffer, bufsize); + if (itf == ITF_KEYBOARD && buffer[7] == 0xFF) { // reset + *get_send_buffer_size(ITF_KEYBOARD) = 0; + otp_curr_seq = otp_exp_seq = 0; + memset(otp_frame_tx, 0, sizeof(otp_frame_tx)); + } + else if (buffer[7] & 0x80) { // a frame + uint8_t rseq = buffer[7] & 0x1F; + if (rseq < 10) { + if (rseq == 0) { + memset(otp_frame_rx, 0, sizeof(otp_frame_rx)); + } + memcpy(otp_frame_rx + rseq * 7, buffer, 7); + if (rseq == 9) { + DEBUG_DATA(otp_frame_rx, sizeof(otp_frame_rx)); + uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = (otp_frame_rx[66] << 8 | otp_frame_rx[65]); + uint8_t slot_id = otp_frame_rx[64]; + if (residual_crc == rcrc) { + apdu.data = otp_frame_rx; + apdu.nc = 64; + apdu.rdata = otp_frame_tx; + apdu.header[0] = 0; + apdu.header[1] = 0x01; + apdu.header[2] = slot_id; + apdu.header[3] = 0; + int ret = otp_process_apdu(); + if (ret == 0x9000 && res_APDU_size > 0) { + otp_send_frame(apdu.rdata, apdu.rlen); + } + } + else { + printf("[OTP] Bad CRC!\n"); + } + } + } + } + return 1; + } + return 0; +} + +uint16_t otp_hid_get_report_cb(uint8_t itf, + uint8_t report_id, + hid_report_type_t report_type, + uint8_t *buffer, + uint16_t reqlen) { + // TODO not Implemented + (void) itf; + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; + printf("get_report %d %d %d\n", itf, report_id, report_type); + DEBUG_PAYLOAD(buffer, reqlen); + uint16_t send_buffer_size = *get_send_buffer_size(ITF_KEYBOARD); + if (send_buffer_size > 0) { + uint8_t seq = otp_curr_seq++; + memset(buffer, 0, 8); + memcpy(buffer, otp_frame_tx + 7 * seq, MIN(7, send_buffer_size)); + buffer[7] = 0x40 | seq; + DEBUG_DATA(buffer, 8); + *get_send_buffer_size(ITF_KEYBOARD) -= MIN(7, send_buffer_size); + } + else if (otp_curr_seq == otp_exp_seq && otp_exp_seq > 0) { + memset(buffer, 0, 7); + buffer[7] = 0x40; + DEBUG_DATA(buffer,8); + otp_curr_seq = otp_exp_seq = 0; + } + else { + otp_status(); + memcpy(buffer, res_APDU, 7); + } + + return reqlen; +} + +#endif From 440ec5c85420ea56e3c42ac927f66b3ff2378301 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 11:49:42 +0100 Subject: [PATCH 16/28] Update SDK to new otp. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index d580194..c9cb330 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit d58019403007d18ba10c0f490f0338747d577500 +Subproject commit c9cb330a07fa2bcd33a354d903aec86b0e08b145 From 27b9e3954aa70237e5bfa55477ace0bd5b6b3e83 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 11:57:08 +0100 Subject: [PATCH 17/28] Use get_version_major and get_version_minor as pointers. Signed-off-by: Pol Henarejos --- src/fido/fido.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/fido/fido.c b/src/fido/fido.c index 4431136..be9c685 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -54,6 +54,13 @@ const uint8_t atr_fido[] = { 0x75, 0x62, 0x69, 0x4b, 0x65, 0x79, 0x40 }; +uint8_t fido_get_version_major() { + return PICO_FIDO_VERSION_MAJOR; +} +uint8_t fido_get_version_minor() { + return PICO_FIDO_VERSION_MINOR; +} + int fido_select(app_t *a) { if (cap_supported(CAP_FIDO2)) { a->process_apdu = fido_process_apdu; @@ -63,24 +70,22 @@ int fido_select(app_t *a) { return CCID_ERR_FILE_NOT_FOUND; } +extern uint8_t (*get_version_major)(); +extern uint8_t (*get_version_minor)(); + void __attribute__((constructor)) fido_ctor() { #if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION) ccid_atr = atr_fido; #endif register_app(fido_select, fido_aid); + get_version_major = fido_get_version_major; + get_version_minor = fido_get_version_minor; } int fido_unload() { return CCID_OK; } -uint8_t get_version_major() { - return PICO_FIDO_VERSION_MAJOR; -} -uint8_t get_version_minor() { - return PICO_FIDO_VERSION_MINOR; -} - mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve) { if (curve == FIDO2_CURVE_P256) { return MBEDTLS_ECP_DP_SECP256R1; From 5c20909b03144153c00c8e0bea5860b7b2a405b6 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 13:01:10 +0100 Subject: [PATCH 18/28] Move some functions from HID to fido callbacks. Signed-off-by: Pol Henarejos --- src/fido/fido.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/fido/fido.c b/src/fido/fido.c index be9c685..b990b14 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -43,7 +43,7 @@ pinUvAuthToken_t paut = { 0 }; uint8_t keydev_dec[32]; bool has_keydev_dec = false; -const uint8_t fido_aid[] = { +const uint8_t _fido_aid[] = { 8, 0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 }; @@ -72,14 +72,24 @@ int fido_select(app_t *a) { extern uint8_t (*get_version_major)(); extern uint8_t (*get_version_minor)(); +extern const uint8_t *fido_aid; +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); void __attribute__((constructor)) fido_ctor() { #if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION) ccid_atr = atr_fido; #endif - register_app(fido_select, fido_aid); get_version_major = fido_get_version_major; get_version_minor = fido_get_version_minor; + fido_aid = _fido_aid; + init_fido_cb = init_fido; + cbor_thread_func = cbor_thread; + cbor_process_cb = cbor_process; + register_app(fido_select, fido_aid); } int fido_unload() { From b493a81ddce0911165f529990440938f25c68287 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 14:27:57 +0100 Subject: [PATCH 19/28] Rename old pico-hsm-sdk to the new pico-keys-sdk. Signed-off-by: Pol Henarejos --- .gitmodules | 2 +- pico-hsm-sdk => pico-keys-sdk | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename pico-hsm-sdk => pico-keys-sdk (100%) diff --git a/.gitmodules b/.gitmodules index 6e06e69..5609c7f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "pico-hsm-sdk"] - path = pico-hsm-sdk + path = pico-keys-sdk url = ../pico-hsm-sdk diff --git a/pico-hsm-sdk b/pico-keys-sdk similarity index 100% rename from pico-hsm-sdk rename to pico-keys-sdk From f8d4f1d02e860cc5dd77def8ad88505a22096200 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 14:28:09 +0100 Subject: [PATCH 20/28] Use new pico-keys-sdk submodule name. Signed-off-by: Pol Henarejos --- .gitmodules | 4 ++-- pico-keys-sdk | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 5609c7f..852c02c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "pico-hsm-sdk"] +[submodule "pico-keys-sdk"] path = pico-keys-sdk - url = ../pico-hsm-sdk + url = https://github.com/polhenarejos/pico-keys-sdk diff --git a/pico-keys-sdk b/pico-keys-sdk index c9cb330..09276f7 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit c9cb330a07fa2bcd33a354d903aec86b0e08b145 +Subproject commit 09276f7117beb7a2f52e65cc601b9153e7b59ca1 From d78d9d10aaf8fe2f0d29b54c05cf28005930a431 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 15:22:28 +0100 Subject: [PATCH 21/28] Use new names and defines. Signed-off-by: Pol Henarejos --- CMakeLists.txt | 4 ++-- src/fido/cbor_client_pin.c | 10 +++++----- src/fido/cbor_config.c | 2 +- src/fido/cbor_cred_mgmt.c | 2 +- src/fido/cbor_get_assertion.c | 2 +- src/fido/cbor_large_blobs.c | 2 +- src/fido/cbor_make_credential.c | 2 +- src/fido/cbor_vendor.c | 2 +- src/fido/cmd_authenticate.c | 2 +- src/fido/cmd_register.c | 2 +- src/fido/cmd_version.c | 2 +- src/fido/credential.c | 2 +- src/fido/fido.c | 2 +- src/fido/management.c | 2 +- src/fido/oath.c | 2 +- src/fido/otp.c | 2 +- 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eee727..a5f60bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,7 +109,7 @@ set(SOURCES ${SOURCES} endif() set(USB_ITF_HID 1) -include(pico-hsm-sdk/pico_hsm_sdk_import.cmake) +include(pico-keys-sdk/pico_keys_sdk_import.cmake) set(INCLUDES ${INCLUDES} ${CMAKE_CURRENT_LIST_DIR}/src/fido @@ -147,5 +147,5 @@ target_compile_options(pico_fido PUBLIC endif (APPLE) else() pico_add_extra_outputs(pico_fido) -target_link_libraries(pico_fido PRIVATE pico_hsm_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board) +target_link_libraries(pico_fido PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board) endif() diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c index f47c09e..c7c13d8 100644 --- a/src/fido/cbor_client_pin.c +++ b/src/fido/cbor_client_pin.c @@ -31,7 +31,7 @@ #include "files.h" #include "random.h" #include "crypto_utils.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" uint32_t usage_timer = 0, initial_usage_time_limit = 0; @@ -181,12 +181,12 @@ int resetPinUvAuthToken() { int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_len, uint8_t *out) { if (protocol == 1) { memcpy(out, in, in_len); - return aes_encrypt(key, NULL, 32 * 8, HSM_AES_MODE_CBC, out, in_len); + return aes_encrypt(key, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len); } else if (protocol == 2) { random_gen(NULL, out, IV_SIZE); memcpy(out + IV_SIZE, in, in_len); - return aes_encrypt(key + 32, out, 32 * 8, HSM_AES_MODE_CBC, out + IV_SIZE, in_len); + return aes_encrypt(key + 32, out, 32 * 8, PICO_KEYS_AES_MODE_CBC, out + IV_SIZE, in_len); } return -1; @@ -195,11 +195,11 @@ int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_l int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_len, uint8_t *out) { if (protocol == 1) { memcpy(out, in, in_len); - return aes_decrypt(key, NULL, 32 * 8, HSM_AES_MODE_CBC, out, in_len); + 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); - return aes_decrypt(key + 32, in, 32 * 8, HSM_AES_MODE_CBC, out, in_len - IV_SIZE); + return aes_decrypt(key + 32, in, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len - IV_SIZE); } return -1; diff --git a/src/fido/cbor_config.c b/src/fido/cbor_config.c index 0d6aeb8..4026cc7 100644 --- a/src/fido/cbor_config.c +++ b/src/fido/cbor_config.c @@ -22,7 +22,7 @@ #include "files.h" #include "apdu.h" #include "credential.h" -#include "hsm.h" +#include "pico_keys.h" #include "random.h" #include "mbedtls/ecdh.h" #include "mbedtls/chachapoly.h" diff --git a/src/fido/cbor_cred_mgmt.c b/src/fido/cbor_cred_mgmt.c index 7f5bf3f..68e95a8 100644 --- a/src/fido/cbor_cred_mgmt.c +++ b/src/fido/cbor_cred_mgmt.c @@ -22,7 +22,7 @@ #include "files.h" #include "apdu.h" #include "credential.h" -#include "hsm.h" +#include "pico_keys.h" uint8_t rp_counter = 1; uint8_t rp_total = 0; diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c index 8dfb206..f3a2516 100644 --- a/src/fido/cbor_get_assertion.c +++ b/src/fido/cbor_get_assertion.c @@ -24,7 +24,7 @@ #include "fido.h" #include "files.h" #include "crypto_utils.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "cbor_make_credential.h" #include "credential.h" diff --git a/src/fido/cbor_large_blobs.c b/src/fido/cbor_large_blobs.c index 4948457..c3ebd70 100644 --- a/src/fido/cbor_large_blobs.c +++ b/src/fido/cbor_large_blobs.c @@ -21,7 +21,7 @@ #include "hid/ctap_hid.h" #include "files.h" #include "apdu.h" -#include "hsm.h" +#include "pico_keys.h" #include "mbedtls/sha256.h" static uint64_t expectedLength = 0, expectedNextOffset = 0; diff --git a/src/fido/cbor_make_credential.c b/src/fido/cbor_make_credential.c index 832ee35..44a488f 100644 --- a/src/fido/cbor_make_credential.c +++ b/src/fido/cbor_make_credential.c @@ -25,7 +25,7 @@ #include "credential.h" #include "mbedtls/sha256.h" #include "random.h" -#include "hsm.h" +#include "pico_keys.h" int cbor_make_credential(const uint8_t *data, size_t len) { CborParser parser; diff --git a/src/fido/cbor_vendor.c b/src/fido/cbor_vendor.c index f76de3c..afe939b 100644 --- a/src/fido/cbor_vendor.c +++ b/src/fido/cbor_vendor.c @@ -21,7 +21,7 @@ #include "hid/ctap_hid.h" #include "files.h" #include "apdu.h" -#include "hsm.h" +#include "pico_keys.h" #include "random.h" #include "mbedtls/ecdh.h" #include "mbedtls/chachapoly.h" diff --git a/src/fido/cmd_authenticate.c b/src/fido/cmd_authenticate.c index 3bea9e6..6f458d6 100644 --- a/src/fido/cmd_authenticate.c +++ b/src/fido/cmd_authenticate.c @@ -16,7 +16,7 @@ */ #include "fido.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "ctap.h" #include "random.h" diff --git a/src/fido/cmd_register.c b/src/fido/cmd_register.c index 1be7e55..7962719 100644 --- a/src/fido/cmd_register.c +++ b/src/fido/cmd_register.c @@ -16,7 +16,7 @@ */ #include "fido.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "ctap.h" #include "random.h" diff --git a/src/fido/cmd_version.c b/src/fido/cmd_version.c index 6a3b132..7b0ff74 100644 --- a/src/fido/cmd_version.c +++ b/src/fido/cmd_version.c @@ -16,7 +16,7 @@ */ #include "apdu.h" -#include "hsm.h" +#include "pico_keys.h" int cmd_version() { memcpy(res_APDU, "U2F_V2", strlen("U2F_V2")); diff --git a/src/fido/credential.c b/src/fido/credential.c index 7e766c6..b43388b 100644 --- a/src/fido/credential.c +++ b/src/fido/credential.c @@ -26,7 +26,7 @@ #include "ctap.h" #include "random.h" #include "files.h" -#include "hsm.h" +#include "pico_keys.h" int credential_derive_chacha_key(uint8_t *outk); diff --git a/src/fido/fido.c b/src/fido/fido.c index b990b14..ab0cc1b 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -16,7 +16,7 @@ */ #include "fido.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "ctap.h" #include "files.h" diff --git a/src/fido/management.c b/src/fido/management.c index 5d4eefb..f835b73 100644 --- a/src/fido/management.c +++ b/src/fido/management.c @@ -16,7 +16,7 @@ */ #include "fido.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "version.h" #include "files.h" diff --git a/src/fido/oath.c b/src/fido/oath.c index d2615c7..cfeb390 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -16,7 +16,7 @@ */ #include "fido.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "files.h" #include "random.h" diff --git a/src/fido/otp.c b/src/fido/otp.c index 65f4bdb..9b31027 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -16,7 +16,7 @@ */ #include "fido.h" -#include "hsm.h" +#include "pico_keys.h" #include "apdu.h" #include "files.h" #include "random.h" From ffb3beb84ab1cd1d8986c4d5f254de0e7c49d545 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 6 Nov 2023 15:32:25 +0100 Subject: [PATCH 22/28] Fix build in emulation mode. Signed-off-by: Pol Henarejos --- src/fido/fido.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fido/fido.c b/src/fido/fido.c index ab0cc1b..d340f33 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -87,7 +87,9 @@ void __attribute__((constructor)) fido_ctor() { get_version_minor = fido_get_version_minor; fido_aid = _fido_aid; 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); } From 1ee86f8634a8f919f8e882e25eaadab071a767a3 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 16 Nov 2023 20:12:01 +0100 Subject: [PATCH 23/28] Moving Pico Keys SDK pointer. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 09276f7..f0687c1 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 09276f7117beb7a2f52e65cc601b9153e7b59ca1 +Subproject commit f0687c1ef392c2bcb293ea554f1dd8b784484922 From 195096ad5205c28c4877e3cb52bd468235ef049a Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 16 Nov 2023 20:12:48 +0100 Subject: [PATCH 24/28] otp must be initialized when selection fido or management applets. Signed-off-by: Pol Henarejos --- src/fido/fido.c | 2 ++ src/fido/management.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/fido/fido.c b/src/fido/fido.c index d340f33..79a935d 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -398,8 +398,10 @@ void scan_all() { scan_files(); } +extern void init_otp(); void init_fido() { scan_all(); + init_otp(); } bool wait_button_pressed() { diff --git a/src/fido/management.c b/src/fido/management.c index f835b73..83cbd43 100644 --- a/src/fido/management.c +++ b/src/fido/management.c @@ -31,6 +31,7 @@ const uint8_t man_aid[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 }; extern void scan_all(); +extern void init_otp(); int man_select(app_t *a) { a->process_apdu = man_process_apdu; a->unload = man_unload; @@ -38,6 +39,7 @@ int man_select(app_t *a) { res_APDU_size = strlen((char *) res_APDU); apdu.ne = res_APDU_size; scan_all(); + init_otp(); return CCID_OK; } From 96de6efed6f981ade100a895d0ffc8325fa447e8 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 16 Nov 2023 20:16:23 +0100 Subject: [PATCH 25/28] OTP static passwords are 38 bytes length. A static password uses fixed, uid and key fields (sum 38). However, Yubikey sets short_ticket flag which implies the half of the password is sent. Fixes #29. Signed-off-by: Pol Henarejos --- src/fido/otp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/fido/otp.c b/src/fido/otp.c index 9b31027..52f1f8b 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -270,10 +270,11 @@ int otp_button_pressed(uint8_t slot) { } } else if (otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET) { + uint8_t fixed_size = FIXED_SIZE + UID_SIZE + KEY_SIZE; if (otp_config->cfg_flags & SHORT_TICKET) { - otp_config->fixed_size /= 2; + fixed_size /= 2; } - add_keyboard_buffer(otp_config->fixed_data, otp_config->fixed_size, false); + add_keyboard_buffer(otp_config->fixed_data, fixed_size, false); if (otp_config->tkt_flags & APPEND_CR) { append_keyboard_buffer((const uint8_t *) "\x28", 1); } From 1ce0d98c3497360f1acaefa83a0c0308f8e1c91f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 21 Nov 2023 11:42:27 +0100 Subject: [PATCH 26/28] OTP callbacks must be initialized on ctor. Fixes #30. Signed-off-by: Pol Henarejos --- src/fido/otp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/fido/otp.c b/src/fido/otp.c index 52f1f8b..58b7e34 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -175,10 +175,6 @@ void init_otp() { } scanned = true; low_flash_available(); -#ifndef ENABLE_EMULATION - hid_set_report_cb = otp_hid_set_report_cb; - hid_get_report_cb = otp_hid_get_report_cb; -#endif } } extern int calculate_oath(uint8_t truncate, @@ -337,6 +333,10 @@ int otp_button_pressed(uint8_t slot) { void __attribute__((constructor)) otp_ctor() { register_app(otp_select, otp_aid); button_pressed_cb = otp_button_pressed; +#ifndef ENABLE_EMULATION + hid_set_report_cb = otp_hid_set_report_cb; + hid_get_report_cb = otp_hid_get_report_cb; +#endif } int otp_unload() { @@ -599,8 +599,6 @@ uint16_t otp_hid_get_report_cb(uint8_t itf, (void) report_type; (void) buffer; (void) reqlen; - printf("get_report %d %d %d\n", itf, report_id, report_type); - DEBUG_PAYLOAD(buffer, reqlen); uint16_t send_buffer_size = *get_send_buffer_size(ITF_KEYBOARD); if (send_buffer_size > 0) { uint8_t seq = otp_curr_seq++; From e757ad294577e2688a53425f2c433b3175cd2322 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 21 Nov 2023 11:53:47 +0100 Subject: [PATCH 27/28] Removing SHORT_TICKET limitation. It is not used to return the half of ticket, but to combine with static to produce hex scancodes. Fixes #29. Signed-off-by: Pol Henarejos --- src/fido/otp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fido/otp.c b/src/fido/otp.c index 58b7e34..e37e779 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -267,8 +267,8 @@ int otp_button_pressed(uint8_t slot) { } else if (otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET) { uint8_t fixed_size = FIXED_SIZE + UID_SIZE + KEY_SIZE; - if (otp_config->cfg_flags & SHORT_TICKET) { - fixed_size /= 2; + if (otp_config->cfg_flags & SHORT_TICKET) { // Not clear which is the purpose of SHORT_TICKET + //fixed_size /= 2; } add_keyboard_buffer(otp_config->fixed_data, fixed_size, false); if (otp_config->tkt_flags & APPEND_CR) { From 20a8ef08f06f067d816e8d5530538ebf72ade953 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 21 Nov 2023 12:01:47 +0100 Subject: [PATCH 28/28] Upgrade to version 5.8 Signed-off-by: Pol Henarejos --- build_pico_fido.sh | 2 +- src/fido/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build_pico_fido.sh b/build_pico_fido.sh index 1e51c67..04945c3 100755 --- a/build_pico_fido.sh +++ b/build_pico_fido.sh @@ -1,7 +1,7 @@ #!/bin/bash VERSION_MAJOR="5" -VERSION_MINOR="6" +VERSION_MINOR="8" rm -rf release/* cd build_release diff --git a/src/fido/version.h b/src/fido/version.h index 721a0bf..789f039 100644 --- a/src/fido/version.h +++ b/src/fido/version.h @@ -18,7 +18,7 @@ #ifndef __VERSION_H_ #define __VERSION_H_ -#define PICO_FIDO_VERSION 0x0506 +#define PICO_FIDO_VERSION 0x0508 #define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff) #define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff)