From 8c2e2386a923cf4bd905e94bfb982879cd591936 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 3 Jul 2019 20:35:50 +0300 Subject: [PATCH 01/24] fix `NFC applet selection does not work correctly` #213 --- targets/stm32l432/src/nfc.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 51e34bb2..d9a5ecaf 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -385,25 +385,47 @@ void rblock_acknowledge() nfc_write_frame(buf,1); } +// international AID = RID:PIX +// RID length == 5 bytes +// usually aid length must be between 5 and 16 bytes +int applet_cmp(uint8_t * aid, int len, uint8_t * const_aid, int const_len) +{ + if (len > const_len) + return 10; + + // if international AID + if (const_aid[0] & 0xf0 == 0xa0) + { + if (len < 5) + return 11; + return memcmp(aid, const_aid, MIN(len, const_len)); + } else { + if (len != const_len) + return 11; + + return memcmp(aid, const_aid, const_len); + } +} + // Selects application. Returns 1 if success, 0 otherwise int select_applet(uint8_t * aid, int len) { - if (memcmp(aid,AID_FIDO,sizeof(AID_FIDO)) == 0) + if (applet_cmp(aid, len, AID_FIDO, sizeof(AID_FIDO) - 1) == 0) { NFC_STATE.selected_applet = APP_FIDO; return APP_FIDO; } - else if (memcmp(aid,AID_NDEF_TYPE_4,sizeof(AID_NDEF_TYPE_4)) == 0) + else if (applet_cmp(aid, len, AID_NDEF_TYPE_4, sizeof(AID_NDEF_TYPE_4) - 1) == 0) { NFC_STATE.selected_applet = APP_NDEF_TYPE_4; return APP_NDEF_TYPE_4; } - else if (memcmp(aid,AID_CAPABILITY_CONTAINER,sizeof(AID_CAPABILITY_CONTAINER)) == 0) + else if (applet_cmp(aid, len, AID_CAPABILITY_CONTAINER, sizeof(AID_CAPABILITY_CONTAINER) - 1) == 0) { NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER; return APP_CAPABILITY_CONTAINER; } - else if (memcmp(aid,AID_NDEF_TAG,sizeof(AID_NDEF_TAG)) == 0) + else if (applet_cmp(aid, len, AID_NDEF_TAG, sizeof(AID_NDEF_TAG) - 1) == 0) { NFC_STATE.selected_applet = APP_NDEF_TAG; return APP_NDEF_TAG; From 4dc6bcf7716d4e6ba7f4bf95867d05298088af27 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 3 Jul 2019 23:01:37 +0300 Subject: [PATCH 02/24] apdu decode sketch --- targets/stm32l432/src/nfc.c | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index d9a5ecaf..44c2d013 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -435,24 +435,27 @@ int select_applet(uint8_t * aid, int len) void nfc_process_iblock(uint8_t * buf, int len) { - APDU_HEADER * apdu = (APDU_HEADER *)(buf + 1); - uint8_t * payload = buf + 1 + 5; - uint8_t plen = apdu->lc; int selected; CTAP_RESPONSE ctap_resp; int status; + + APDU_STRUCT apdu; + apdu_decode(buf + 1, len - 1, &apdu); + uint16_t plen = apdu.lc; + //APDU_HEADER * apdu = (APDU_HEADER *)(buf + 1); + //uint8_t * payload = buf + 1 + 5; ---- apdu.data printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); // TODO this needs to be organized better - switch(apdu->ins) + switch(apdu.ins) { case APDU_INS_SELECT: if (plen > len - 6) { - printf1(TAG_ERR, "Truncating APDU length %d\r\n", apdu->lc); - plen = len-6; + printf1(TAG_ERR, "Truncating APDU length %d\r\n", apdu.lc); + plen = len - 6; } // if (apdu->p1 == 0 && apdu->p2 == 0x0c) // { @@ -468,7 +471,7 @@ void nfc_process_iblock(uint8_t * buf, int len) // } // else { - selected = select_applet(payload, plen); + selected = select_applet(apdu.data, apdu.lc); if (selected == APP_FIDO) { // block = buf[0] & 1; @@ -487,7 +490,7 @@ void nfc_process_iblock(uint8_t * buf, int len) else { nfc_write_response(buf[0], SW_FILE_NOT_FOUND); - printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC,payload, plen); + printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC, apdu.data, apdu.lc); } } break; @@ -511,9 +514,9 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC, "U2F Register command.\r\n"); - if (plen != 64) + if (apdu.lc != 64) { - printf1(TAG_NFC, "U2F Register request length error. len=%d.\r\n", plen); + printf1(TAG_NFC, "U2F Register request length error. len=%d.\r\n", apdu.lc); nfc_write_response(buf[0], SW_WRONG_LENGTH); return; } @@ -535,9 +538,6 @@ void nfc_process_iblock(uint8_t * buf, int len) // printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); - - - printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), timestamp()); break; @@ -549,10 +549,10 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC, "U2F Authenticate command.\r\n"); - if (plen != 64 + 1 + buf[6 + 64]) + if (apdu.lc != 64 + 1 + buf[6 + 64]) { delay(5); - printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", plen, buf[6 + 64]); + printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", apdu.lc, buf[6 + 64]); nfc_write_response(buf[0], SW_WRONG_LENGTH); return; } @@ -579,7 +579,7 @@ void nfc_process_iblock(uint8_t * buf, int len) WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); - status = ctap_request(payload, plen, &ctap_resp); + status = ctap_request(apdu.data, apdu.lc, &ctap_resp); if (!WTX_off()) return; @@ -603,14 +603,13 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_INS_READ_BINARY: - switch(NFC_STATE.selected_applet) { case APP_CAPABILITY_CONTAINER: printf1(TAG_NFC,"APP_CAPABILITY_CONTAINER\r\n"); if (plen > 15) { - printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); + printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu.lc); plen = 15; } nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, plen, SW_SUCCESS); @@ -620,7 +619,7 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC,"APP_NDEF_TAG\r\n"); if (plen > (sizeof(NDEF_SAMPLE) - 1)) { - printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); + printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu.lc); plen = sizeof(NDEF_SAMPLE) - 1; } nfc_write_response_ex(buf[0], NDEF_SAMPLE, plen, SW_SUCCESS); @@ -634,7 +633,7 @@ void nfc_process_iblock(uint8_t * buf, int len) break; default: - printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu->ins); + printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu.ins); nfc_write_response(buf[0], SW_INS_INVALID); break; } From a51c9192b178c7ad389de1e8d63760cb2ceea02c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 16:27:33 +0300 Subject: [PATCH 03/24] add apdu_decode --- fido2/apdu.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ fido2/apdu.h | 26 +++++++++++ 2 files changed, 145 insertions(+) create mode 100644 fido2/apdu.c diff --git a/fido2/apdu.c b/fido2/apdu.c new file mode 100644 index 00000000..b2516ea7 --- /dev/null +++ b/fido2/apdu.c @@ -0,0 +1,119 @@ +// Copyright 2019 SoloKeys Developers +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +// iso7816:2013. 5.3.2 Decoding conventions for command bodies + +#include "apdu.h" + +int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) +{ + EXT_APDU_HEADER *hapdu = (EXT_APDU_HEADER *)data; + + apdu->cla = hapdu->cla; + apdu->ins = hapdu->ins; + apdu->p1 = hapdu->p1; + apdu->p2 = hapdu->p2; + + apdu->lc = 0; + apdu->data = NULL; + apdu->le = 0; + apdu->extended_apdu = false; + apdu->case_type = 0x00; + + uint8_t b0 = hapdu->lc[0]; + + // case 1 + if (len == 4) + { + apdu->case_type = 0x01; + } + + // case 2S (Le) + if (len == 5 && b0 != 0) + { + apdu->case_type = 0x02; + apdu->le = b0; + if (!apdu->le) + apdu->le = 0x100; + } + + // case 3S (Lc + data) + if (len == 5U + b0 && b0 != 0) + { + apdu->case_type = 0x13; + apdu->lc = (hapdu->lc[1] << 8) + hapdu->lc[2]; + } + + // case 4S (Lc + data + Le) + if (len == 5U + b0 + 1U && b0 != 0) + { + apdu->case_type = 0x04; + apdu->lc = b0; + apdu->le = data[len - 1]; + if (!apdu->le) + apdu->le = 0x100; + } + + // extended length apdu + if (len >= 7 && b0 == 0) + { + uint16_t extlen = (hapdu->lc[1] << 8) + hapdu->lc[2]; + + // case 2E (Le) - extended + if (len == 7) + { + apdu->case_type = 0x12; + apdu->extended_apdu = true; + apdu->le = extlen; + if (!apdu->le) + apdu->le = 0x10000; + } + + // case 3E (Lc + data) - extended + if (len == 7U + extlen) + { + apdu->case_type = 0x13; + apdu->lc = extlen; + } + + // case 4E (Lc + data + Le) - extended 2-byte Le + if (len == 7U + extlen + 2U) + { + apdu->case_type = 0x14; + apdu->lc = extlen; + apdu->le = (data[len - 2] << 8) + data[len - 1]; + if (!apdu->le) + apdu->le = 0x10000; + } + + // case 4E (Lc + data + Le) - extended 3-byte Le + if (len == 7U + extlen + 3U && data[len - 3] == 0) + { + apdu->case_type = 0x24; + apdu->lc = extlen; + apdu->le = (data[len - 2] << 8) + data[len - 1]; + if (!apdu->le) + apdu->le = 0x10000; + } + } + + if (!apdu->case_type) + return 1; + + if (apdu->lc) + { + if (apdu->extended_apdu) + { + apdu->data = data + 5; + } else { + apdu->data = data + 7; + } + + } + + return 0; +} diff --git a/fido2/apdu.h b/fido2/apdu.h index d9687c79..ff3940c8 100644 --- a/fido2/apdu.h +++ b/fido2/apdu.h @@ -2,6 +2,8 @@ #define _APDU_H_ #include +#include +#include typedef struct { @@ -12,6 +14,30 @@ typedef struct uint8_t lc; } __attribute__((packed)) APDU_HEADER; +typedef struct +{ + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t lc[3]; +} __attribute__((packed)) EXT_APDU_HEADER; + +typedef struct +{ + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint16_t lc; + uint8_t *data; + uint32_t le; + bool extended_apdu; + uint8_t case_type; +} __attribute__((packed)) APDU_STRUCT; + +extern int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu); + #define APDU_FIDO_U2F_REGISTER 0x01 #define APDU_FIDO_U2F_AUTHENTICATE 0x02 #define APDU_FIDO_U2F_VERSION 0x03 From 236498ee03997cc937a591c6934bbeec190480b7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 16:27:57 +0300 Subject: [PATCH 04/24] add make --- targets/stm32l432/build/application.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/build/application.mk b/targets/stm32l432/build/application.mk index e482f877..848887f1 100644 --- a/targets/stm32l432/build/application.mk +++ b/targets/stm32l432/build/application.mk @@ -7,7 +7,7 @@ SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c SRC += $(DRIVER_LIBS) $(USB_LIB) # FIDO2 lib -SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c +SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c SRC += ../../fido2/ctap_parse.c ../../fido2/main.c SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c From d2c85881e612d0e205f18da800b797e10b7646bb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 16:29:30 +0300 Subject: [PATCH 05/24] applet selection and apdu check --- targets/stm32l432/src/nfc.c | 49 ++++++++++++++----------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 44c2d013..9a2a8596 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -394,7 +394,7 @@ int applet_cmp(uint8_t * aid, int len, uint8_t * const_aid, int const_len) return 10; // if international AID - if (const_aid[0] & 0xf0 == 0xa0) + if ((const_aid[0] & 0xf0) == 0xa0) { if (len < 5) return 11; @@ -410,22 +410,22 @@ int applet_cmp(uint8_t * aid, int len, uint8_t * const_aid, int const_len) // Selects application. Returns 1 if success, 0 otherwise int select_applet(uint8_t * aid, int len) { - if (applet_cmp(aid, len, AID_FIDO, sizeof(AID_FIDO) - 1) == 0) + if (applet_cmp(aid, len, (uint8_t *)AID_FIDO, sizeof(AID_FIDO) - 1) == 0) { NFC_STATE.selected_applet = APP_FIDO; return APP_FIDO; } - else if (applet_cmp(aid, len, AID_NDEF_TYPE_4, sizeof(AID_NDEF_TYPE_4) - 1) == 0) + else if (applet_cmp(aid, len, (uint8_t *)AID_NDEF_TYPE_4, sizeof(AID_NDEF_TYPE_4) - 1) == 0) { NFC_STATE.selected_applet = APP_NDEF_TYPE_4; return APP_NDEF_TYPE_4; } - else if (applet_cmp(aid, len, AID_CAPABILITY_CONTAINER, sizeof(AID_CAPABILITY_CONTAINER) - 1) == 0) + else if (applet_cmp(aid, len, (uint8_t *)AID_CAPABILITY_CONTAINER, sizeof(AID_CAPABILITY_CONTAINER) - 1) == 0) { NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER; return APP_CAPABILITY_CONTAINER; } - else if (applet_cmp(aid, len, AID_NDEF_TAG, sizeof(AID_NDEF_TAG) - 1) == 0) + else if (applet_cmp(aid, len, (uint8_t *)AID_NDEF_TAG, sizeof(AID_NDEF_TAG) - 1) == 0) { NFC_STATE.selected_applet = APP_NDEF_TAG; return APP_NDEF_TAG; @@ -438,12 +438,10 @@ void nfc_process_iblock(uint8_t * buf, int len) int selected; CTAP_RESPONSE ctap_resp; int status; + uint16_t reslen; APDU_STRUCT apdu; apdu_decode(buf + 1, len - 1, &apdu); - uint16_t plen = apdu.lc; - //APDU_HEADER * apdu = (APDU_HEADER *)(buf + 1); - //uint8_t * payload = buf + 1 + 5; ---- apdu.data printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); @@ -452,11 +450,6 @@ void nfc_process_iblock(uint8_t * buf, int len) switch(apdu.ins) { case APDU_INS_SELECT: - if (plen > len - 6) - { - printf1(TAG_ERR, "Truncating APDU length %d\r\n", apdu.lc); - plen = len - 6; - } // if (apdu->p1 == 0 && apdu->p2 == 0x0c) // { // printf1(TAG_NFC,"Select NDEF\r\n"); @@ -527,9 +520,9 @@ void nfc_process_iblock(uint8_t * buf, int len) // WTX_on(WTX_TIME_DEFAULT); // SystemClock_Config_LF32(); // delay(300); - if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_FAST);; + if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_FAST); u2f_request_nfc(&buf[1], len, &ctap_resp); - if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_IDLE);; + if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_IDLE); // if (!WTX_off()) // return; @@ -572,7 +565,7 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_NFCCTAP_MSG: if (NFC_STATE.selected_applet != APP_FIDO) { nfc_write_response(buf[0], SW_INS_INVALID); - break; + return; } printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp()); @@ -602,36 +595,32 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_INS_READ_BINARY: - + // response length + reslen = apdu.le & 0xffff; switch(NFC_STATE.selected_applet) { case APP_CAPABILITY_CONTAINER: printf1(TAG_NFC,"APP_CAPABILITY_CONTAINER\r\n"); - if (plen > 15) - { - printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu.lc); - plen = 15; - } - nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, plen, SW_SUCCESS); + if (reslen == 0 || reslen > sizeof(NFC_CC) - 1) + reslen = sizeof(NFC_CC) - 1; + nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, reslen, SW_SUCCESS); ams_wait_for_tx(10); break; case APP_NDEF_TAG: printf1(TAG_NFC,"APP_NDEF_TAG\r\n"); - if (plen > (sizeof(NDEF_SAMPLE) - 1)) - { - printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu.lc); - plen = sizeof(NDEF_SAMPLE) - 1; - } - nfc_write_response_ex(buf[0], NDEF_SAMPLE, plen, SW_SUCCESS); + if (reslen == 0 || reslen > sizeof(NDEF_SAMPLE) - 1) + reslen = sizeof(NDEF_SAMPLE) - 1; + nfc_write_response_ex(buf[0], NDEF_SAMPLE, reslen, SW_SUCCESS); ams_wait_for_tx(10); break; default: + nfc_write_response(buf[0], SW_FILE_NOT_FOUND); printf1(TAG_ERR, "No binary applet selected!\r\n"); return; break; } - break; + default: printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu.ins); nfc_write_response(buf[0], SW_INS_INVALID); From 88a8eba4245a0a4b2bc598e8a2ed16c37f83e90b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 16:32:11 +0300 Subject: [PATCH 06/24] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e80f85c0..41478aa8 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,5 @@ targets/*/docs/ main builds/* +tools/testing/.idea/* +tools/testing/tests/__pycache__/* From 26bc8a2889722a7a1f683c42d4551d18556bc8f1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 17:27:03 +0300 Subject: [PATCH 07/24] apdu decoding works --- fido2/apdu.c | 4 ++-- targets/stm32l432/src/nfc.c | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/fido2/apdu.c b/fido2/apdu.c index b2516ea7..2e8123fb 100644 --- a/fido2/apdu.c +++ b/fido2/apdu.c @@ -44,8 +44,8 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) // case 3S (Lc + data) if (len == 5U + b0 && b0 != 0) { - apdu->case_type = 0x13; - apdu->lc = (hapdu->lc[1] << 8) + hapdu->lc[2]; + apdu->case_type = 0x03; + apdu->lc = b0; } // case 4S (Lc + data + Le) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 9a2a8596..54c38590 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -440,12 +440,24 @@ void nfc_process_iblock(uint8_t * buf, int len) int status; uint16_t reslen; - APDU_STRUCT apdu; - apdu_decode(buf + 1, len - 1, &apdu); - printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); + uint8_t apdu_offset = 1; + // NAD following + if (buf[0] & 0x04) apdu_offset++; + // CID following + if (buf[0] & 0x08) apdu_offset++; + + APDU_STRUCT apdu; + if (apdu_decode(buf + apdu_offset, len - apdu_offset, &apdu)) { + printf1(TAG_NFC,"apdu decode error\n"); + nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); + return; + } + printf1(TAG_NFC,"apdu ok. %scase=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%d le=%d\n", + apdu.extended_apdu ? "[e]":"", apdu.case_type, apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.lc, apdu.le); + // TODO this needs to be organized better switch(apdu.ins) { From 75b1d9cd016cfefc857df81721a814abf8592c9a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 17:38:34 +0300 Subject: [PATCH 08/24] offset calc refactoring --- targets/stm32l432/src/nfc.c | 18 ++++++++++++------ targets/stm32l432/src/nfc.h | 2 ++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 54c38590..7e65def0 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -14,6 +14,16 @@ #define IS_IRQ_ACTIVE() (1 == (LL_GPIO_ReadInputPort(SOLO_AMS_IRQ_PORT) & SOLO_AMS_IRQ_PIN)) +uint8_t p14443_block_offset(uint8_t pcb) { + uint8_t offset = 1; + // NAD following + if (pcb & 0x04) offset++; + // CID following + if (pcb & 0x08) offset++; + + return offset; +} + // Capability container const CAPABILITY_CONTAINER NFC_CC = { .cclen_hi = 0x00, .cclen_lo = 0x0f, @@ -443,14 +453,10 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); - uint8_t apdu_offset = 1; - // NAD following - if (buf[0] & 0x04) apdu_offset++; - // CID following - if (buf[0] & 0x08) apdu_offset++; + uint8_t block_offset = p14443_block_offset(buf[0]); APDU_STRUCT apdu; - if (apdu_decode(buf + apdu_offset, len - apdu_offset, &apdu)) { + if (apdu_decode(buf + block_offset, len - block_offset, &apdu)) { printf1(TAG_NFC,"apdu decode error\n"); nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); return; diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 98715371..f284a8e3 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -40,6 +40,8 @@ typedef struct #define NFC_CMD_SBLOCK 0xc0 #define IS_SBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_SBLOCK) && (((x) & 0x02) == 0x02) ) +extern uint8_t p14443_block_offset(uint8_t pcb); + #define NFC_SBLOCK_DESELECT 0x30 #define NFC_SBLOCK_WTX 0x30 From 4845d2c1725b2905cf479bfe0ed50189d788b9ea Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 17:52:00 +0300 Subject: [PATCH 09/24] fix 14443 apdu decode and select --- fido2/apdu.c | 6 +++--- targets/stm32l432/src/nfc.c | 11 +++-------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/fido2/apdu.c b/fido2/apdu.c index 2e8123fb..3eacdefe 100644 --- a/fido2/apdu.c +++ b/fido2/apdu.c @@ -33,7 +33,7 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) } // case 2S (Le) - if (len == 5 && b0 != 0) + if (len == 5) { apdu->case_type = 0x02; apdu->le = b0; @@ -108,9 +108,9 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) { if (apdu->extended_apdu) { - apdu->data = data + 5; - } else { apdu->data = data + 7; + } else { + apdu->data = data + 5; } } diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 7e65def0..0097a64b 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -457,11 +457,11 @@ void nfc_process_iblock(uint8_t * buf, int len) APDU_STRUCT apdu; if (apdu_decode(buf + block_offset, len - block_offset, &apdu)) { - printf1(TAG_NFC,"apdu decode error\n"); + printf1(TAG_NFC,"apdu decode error\r\n"); nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); return; } - printf1(TAG_NFC,"apdu ok. %scase=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%d le=%d\n", + printf1(TAG_NFC,"apdu ok. %scase=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%d le=%d\r\n", apdu.extended_apdu ? "[e]":"", apdu.case_type, apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.lc, apdu.le); // TODO this needs to be organized better @@ -485,11 +485,6 @@ void nfc_process_iblock(uint8_t * buf, int len) selected = select_applet(apdu.data, apdu.lc); if (selected == APP_FIDO) { - // block = buf[0] & 1; - // block = NFC_STATE.block_num; - // block = !block; - // NFC_STATE.block_num = block; - // NFC_STATE.block_num = block; nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); printf1(TAG_NFC, "FIDO applet selected.\r\n"); } @@ -501,7 +496,7 @@ void nfc_process_iblock(uint8_t * buf, int len) else { nfc_write_response(buf[0], SW_FILE_NOT_FOUND); - printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC, apdu.data, apdu.lc); + printf1(TAG_NFC, "NOT selected "); dump_hex1(TAG_NFC, apdu.data, apdu.lc); } } break; From f2ebaf6abe6e45ea3a17ad071017e3486d838520 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 19:14:26 +0300 Subject: [PATCH 10/24] invalid cla and r-block works --- fido2/apdu.h | 1 + targets/stm32l432/src/nfc.c | 90 ++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/fido2/apdu.h b/fido2/apdu.h index ff3940c8..44029b33 100644 --- a/fido2/apdu.h +++ b/fido2/apdu.h @@ -51,6 +51,7 @@ extern int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu); #define SW_COND_USE_NOT_SATISFIED 0x6985 #define SW_FILE_NOT_FOUND 0x6a82 #define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid +#define SW_CLA_INVALID 0x6e00 #define SW_INTERNAL_EXCEPTION 0x6f00 #endif //_APDU_H_ diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 0097a64b..4cfa7cae 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -171,14 +171,18 @@ bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t r if (len > 32 - 3) return false; - res[0] = NFC_CMD_IBLOCK | (req0 & 3); + res[0] = NFC_CMD_IBLOCK | (req0 & 0x0f); + res[1] = 0; + res[2] = 0; + + uint8_t block_offset = p14443_block_offset(req0); if (len && data) - memcpy(&res[1], data, len); + memcpy(&res[block_offset], data, len); - res[len + 1] = resp >> 8; - res[len + 2] = resp & 0xff; - nfc_write_frame(res, 3 + len); + res[len + block_offset + 0] = resp >> 8; + res[len + block_offset + 1] = resp & 0xff; + nfc_write_frame(res, block_offset + len + 2); return true; } @@ -192,21 +196,24 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) { uint8_t res[32 + 2]; int sendlen = 0; - uint8_t iBlock = NFC_CMD_IBLOCK | (req0 & 3); + uint8_t iBlock = NFC_CMD_IBLOCK | (req0 & 0x0f); + uint8_t block_offset = p14443_block_offset(req0); if (len <= 31) { uint8_t res[32] = {0}; - res[0] = iBlock; + res[0] = iBlock; if (len && data) - memcpy(&res[1], data, len); - nfc_write_frame(res, len + 1); + memcpy(&res[block_offset], data, len); + nfc_write_frame(res, len + block_offset); } else { do { // transmit I block - int vlen = MIN(31, len - sendlen); - res[0] = iBlock; - memcpy(&res[1], &data[sendlen], vlen); + int vlen = MIN(32 - block_offset, len - sendlen); + res[0] = iBlock; + res[1] = 0; + res[2] = 0; + memcpy(&res[block_offset], &data[sendlen], vlen); // if not a last block if (vlen + sendlen < len) @@ -215,7 +222,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) } // send data - nfc_write_frame(res, vlen + 1); + nfc_write_frame(res, vlen + block_offset); sendlen += vlen; // wait for transmit (32 bytes aprox 2,5ms) @@ -236,9 +243,10 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) break; } - if (reclen != 1) + uint8_t rblock_offset = p14443_block_offset(res[0]); + if (reclen != rblock_offset) { - printf1(TAG_NFC, "R block length error. len: %d. %d/%d \r\n", reclen,sendlen,len); + printf1(TAG_NFC, "R block length error. len: %d. %d/%d \r\n", reclen, sendlen, len); dump_hex1(TAG_NFC, recbuf, reclen); break; } @@ -387,12 +395,18 @@ int answer_rats(uint8_t parameter) return 0; } -void rblock_acknowledge() +void rblock_acknowledge(uint8_t req0, bool ack) { - uint8_t buf[32]; + uint8_t buf[32] = {0}; + + uint8_t block_offset = p14443_block_offset(req0); NFC_STATE.block_num = !NFC_STATE.block_num; - buf[0] = NFC_CMD_RBLOCK | NFC_STATE.block_num; - nfc_write_frame(buf,1); + + buf[0] = NFC_CMD_RBLOCK | (req0 & 0x0f); + if (ack) + buf[0] |= NFC_CMD_RBLOCK_ACK; + + nfc_write_frame(buf, block_offset); } // international AID = RID:PIX @@ -464,6 +478,13 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC,"apdu ok. %scase=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%d le=%d\r\n", apdu.extended_apdu ? "[e]":"", apdu.case_type, apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.lc, apdu.le); + // check CLA + if (apdu.cla != 0x00 && apdu.cla != 0x80) { + printf1(TAG_NFC, "Unknown CLA %02x\r\n", apdu.cla); + nfc_write_response(buf[0], SW_CLA_INVALID); + return; + } + // TODO this needs to be organized better switch(apdu.ins) { @@ -639,8 +660,6 @@ void nfc_process_iblock(uint8_t * buf, int len) nfc_write_response(buf[0], SW_INS_INVALID); break; } - - } static uint8_t ibuf[1024]; @@ -654,7 +673,7 @@ void clear_ibuf() void nfc_process_block(uint8_t * buf, unsigned int len) { - + printf1(TAG_NFC, "-----\r\n"); if (!len) return; @@ -664,6 +683,7 @@ void nfc_process_block(uint8_t * buf, unsigned int len) } else if (IS_IBLOCK(buf[0])) { + uint8_t block_offset = p14443_block_offset(buf[0]); if (buf[0] & 0x10) { printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining blen=%d len=%d\r\n", ibuflen, len); @@ -677,27 +697,27 @@ void nfc_process_block(uint8_t * buf, unsigned int len) printf1(TAG_NFC_APDU,"i> "); dump_hex1(TAG_NFC_APDU, buf, len); - if (len) + if (len > block_offset) { - memcpy(&ibuf[ibuflen], &buf[1], len - 1); - ibuflen += len - 1; + memcpy(&ibuf[ibuflen], &buf[block_offset], len - block_offset); + ibuflen += len - block_offset; } // send R block - uint8_t rb = NFC_CMD_RBLOCK | NFC_CMD_RBLOCK_ACK | (buf[0] & 3); - nfc_write_frame(&rb, 1); + rblock_acknowledge(buf[0], true); } else { if (ibuflen) { - if (len) + if (len > block_offset) { - memcpy(&ibuf[ibuflen], &buf[1], len - 1); - ibuflen += len - 1; + memcpy(&ibuf[ibuflen], &buf[block_offset], len - block_offset); + ibuflen += len - block_offset; } - memmove(&ibuf[1], ibuf, ibuflen); - ibuf[0] = buf[0]; - ibuflen++; + // add last chaining to top of the block + memmove(&ibuf[block_offset], ibuf, ibuflen); + memmove(ibuf, buf, block_offset); + ibuflen += block_offset; printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len); @@ -706,7 +726,6 @@ void nfc_process_block(uint8_t * buf, unsigned int len) nfc_process_iblock(ibuf, ibuflen); } else { - // printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); nfc_process_iblock(buf, len); } clear_ibuf(); @@ -714,7 +733,7 @@ void nfc_process_block(uint8_t * buf, unsigned int len) } else if (IS_RBLOCK(buf[0])) { - rblock_acknowledge(); + rblock_acknowledge(buf[0], false); printf1(TAG_NFC, "NFC_CMD_RBLOCK\r\n"); } else if (IS_SBLOCK(buf[0])) @@ -733,6 +752,7 @@ void nfc_process_block(uint8_t * buf, unsigned int len) else { printf1(TAG_NFC, "NFC_CMD_SBLOCK, Unknown. len[%d]\r\n", len); + nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); } dump_hex1(TAG_NFC, buf, len); } From cb76c34ed2a8fd45d2a005901b1aa24a6ebc9740 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 19:45:09 +0300 Subject: [PATCH 11/24] fix addressing --- targets/stm32l432/src/nfc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 4cfa7cae..c06f6cf4 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -554,17 +554,16 @@ void nfc_process_iblock(uint8_t * buf, int len) // WTX_on(WTX_TIME_DEFAULT); // SystemClock_Config_LF32(); // delay(300); - if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_FAST); - u2f_request_nfc(&buf[1], len, &ctap_resp); - if (device_is_nfc()) device_set_clock_rate(DEVICE_LOW_POWER_IDLE); + if (device_is_nfc() == NFC_IS_ACTIVE) device_set_clock_rate(DEVICE_LOW_POWER_FAST); + u2f_request_nfc(&buf[block_offset], len - block_offset, &ctap_resp); + if (device_is_nfc() == NFC_IS_ACTIVE) device_set_clock_rate(DEVICE_LOW_POWER_IDLE); // if (!WTX_off()) // return; + printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register P2 took %d\r\n", timestamp()); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); - // printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); - printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), timestamp()); break; @@ -586,7 +585,7 @@ void nfc_process_iblock(uint8_t * buf, int len) timestamp(); // WTX_on(WTX_TIME_DEFAULT); - u2f_request_nfc(&buf[1], len, &ctap_resp); + u2f_request_nfc(&buf[block_offset], len - block_offset, &ctap_resp); // if (!WTX_off()) // return; From d1df8b8b77f6de5f2e02fde00a02f37fb8b83b91 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 19:54:00 +0300 Subject: [PATCH 12/24] u2f authenticate fix --- targets/stm32l432/src/nfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index c06f6cf4..16d41aa8 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -575,10 +575,10 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC, "U2F Authenticate command.\r\n"); - if (apdu.lc != 64 + 1 + buf[6 + 64]) + if (apdu.lc != 64 + 1 + apdu.data[64]) { delay(5); - printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", apdu.lc, buf[6 + 64]); + printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", apdu.lc, apdu.data[64]); nfc_write_response(buf[0], SW_WRONG_LENGTH); return; } From 151e1d0e9ba46f63c066011e3a1ce4f1fc7b4aeb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 20:09:47 +0300 Subject: [PATCH 13/24] fix some errors in tests --- tools/testing/tests/tester.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/testing/tests/tester.py b/tools/testing/tests/tester.py index 011c1c2f..d05185f6 100644 --- a/tools/testing/tests/tester.py +++ b/tools/testing/tests/tester.py @@ -51,6 +51,7 @@ def __init__(self, tester=None): self.host = "examplo.org" self.user_count = 10 self.is_sim = False + self.nfc_interface_only = False; if tester: self.initFromTester(tester) @@ -61,9 +62,11 @@ def initFromTester(self, tester): self.ctap = tester.ctap self.ctap1 = tester.ctap1 self.client = tester.client + self.nfc_interface_only = tester.nfc_interface_only def find_device(self, nfcInterfaceOnly=False): dev = None + self.nfc_interface_only = nfcInterfaceOnly if not nfcInterfaceOnly: print("--- HID ---") print(list(CtapHidDevice.list_devices())) @@ -102,7 +105,7 @@ def reboot(self,): else: print("Please reboot authentictor and hit enter") input() - self.find_device() + self.find_device(self.nfc_interface_only) def send_data(self, cmd, data): if not isinstance(data, bytes): @@ -196,7 +199,7 @@ def testReset(self,): print("You must power cycle authentictor. Hit enter when done.") input() time.sleep(0.2) - self.find_device() + self.find_device(self.nfc_interface_only) self.ctap.reset() def testMC(self, test, *args, **kwargs): From 2272e69e15d68ed63a6497b71bbb3fcc53f04195 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 20:14:24 +0300 Subject: [PATCH 14/24] fix tests --- tools/testing/tests/fido2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/tests/fido2.py b/tools/testing/tests/fido2.py index 94a361d1..88fbe9d8 100644 --- a/tools/testing/tests/fido2.py +++ b/tools/testing/tests/fido2.py @@ -223,7 +223,7 @@ def test_extensions(self,): with Test("Get shared secret"): key_agreement, shared_secret = ( - self.client.pin_protocol._init_shared_secret() + self.client.pin_protocol.get_shared_secret() ) cipher = Cipher( algorithms.AES(shared_secret), From 4d9285085fca9a7834989e05b6aa23f0bacccf93 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 20:42:24 +0300 Subject: [PATCH 15/24] fix tests --- tools/testing/tests/fido2.py | 4 +--- tools/testing/tests/tester.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/testing/tests/fido2.py b/tools/testing/tests/fido2.py index 88fbe9d8..3b5b5571 100644 --- a/tools/testing/tests/fido2.py +++ b/tools/testing/tests/fido2.py @@ -222,9 +222,7 @@ def test_extensions(self,): ) with Test("Get shared secret"): - key_agreement, shared_secret = ( - self.client.pin_protocol.get_shared_secret() - ) + key_agreement, shared_secret = self.client.pin_protocol.get_shared_secret() cipher = Cipher( algorithms.AES(shared_secret), modes.CBC(b"\x00" * 16), diff --git a/tools/testing/tests/tester.py b/tools/testing/tests/tester.py index d05185f6..ab7c2790 100644 --- a/tools/testing/tests/tester.py +++ b/tools/testing/tests/tester.py @@ -51,7 +51,7 @@ def __init__(self, tester=None): self.host = "examplo.org" self.user_count = 10 self.is_sim = False - self.nfc_interface_only = False; + self.nfc_interface_only = False if tester: self.initFromTester(tester) From 315b6564ab002abc4eef1f035f5513e1763f9ec6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 4 Jul 2019 23:12:31 +0300 Subject: [PATCH 16/24] u2f works with extended apdu and now user presence not needs if request come from nfc and power from usb --- fido2/device.h | 2 ++ fido2/u2f.c | 10 +++++----- fido2/u2f.h | 2 +- targets/stm32l432/src/device.c | 7 ++++++- targets/stm32l432/src/nfc.c | 6 ++++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/fido2/device.h b/fido2/device.h index dfb95ec3..0c11fe8a 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -105,6 +105,8 @@ void device_set_clock_rate(DEVICE_CLOCK_RATE param); #define NFC_IS_AVAILABLE 2 int device_is_nfc(); +void request_from_nfc(bool request_active); + void device_init_button(); #endif diff --git a/fido2/u2f.c b/fido2/u2f.c index 14cb8485..7999ab20 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -113,14 +113,14 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length); } -void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp) +void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp) { - if (len < 5 || !req) + if (!header) return; - uint32_t alen = req[4]; - - u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp); + request_from_nfc(true); // disable presence test + u2f_request_ex((APDU_HEADER *)header, data, datalen, resp); + request_from_nfc(false); // enable presence test } void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) diff --git a/fido2/u2f.h b/fido2/u2f.h index 9055b36c..ad73cc93 100644 --- a/fido2/u2f.h +++ b/fido2/u2f.h @@ -101,7 +101,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp); // u2f_request send a U2F message to NFC protocol // @req data with iso7816 apdu message // @len data length -void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp); +void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp); int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * appid); diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index ae441fc7..62891890 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -43,6 +43,7 @@ uint32_t __last_update = 0; extern PCD_HandleTypeDef hpcd; static int _NFC_status = 0; static bool isLowFreq = 0; +static bool _RequestComeFromNFC = false; // #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) static int is_physical_button_pressed() @@ -57,6 +58,10 @@ static int is_touch_button_pressed() int (*IS_BUTTON_PRESSED)() = is_physical_button_pressed; +void request_from_nfc(bool request_active) { + _RequestComeFromNFC = request_active; +} + // Timer6 overflow handler. happens every ~90ms. void TIM6_DAC_IRQHandler() { @@ -491,7 +496,7 @@ static int handle_packets() int ctap_user_presence_test(uint32_t up_delay) { int ret; - if (device_is_nfc() == NFC_IS_ACTIVE) + if (device_is_nfc() == NFC_IS_ACTIVE || _RequestComeFromNFC) { return 1; } diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 16d41aa8..2c1b34dc 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -555,7 +555,7 @@ void nfc_process_iblock(uint8_t * buf, int len) // SystemClock_Config_LF32(); // delay(300); if (device_is_nfc() == NFC_IS_ACTIVE) device_set_clock_rate(DEVICE_LOW_POWER_FAST); - u2f_request_nfc(&buf[block_offset], len - block_offset, &ctap_resp); + u2f_request_nfc(&buf[block_offset], apdu.data, apdu.lc, &ctap_resp); if (device_is_nfc() == NFC_IS_ACTIVE) device_set_clock_rate(DEVICE_LOW_POWER_IDLE); // if (!WTX_off()) // return; @@ -585,7 +585,7 @@ void nfc_process_iblock(uint8_t * buf, int len) timestamp(); // WTX_on(WTX_TIME_DEFAULT); - u2f_request_nfc(&buf[block_offset], len - block_offset, &ctap_resp); + u2f_request_nfc(&buf[block_offset], apdu.data, apdu.lc, &ctap_resp); // if (!WTX_off()) // return; @@ -604,8 +604,10 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp()); WTX_on(WTX_TIME_DEFAULT); + request_from_nfc(true); ctap_response_init(&ctap_resp); status = ctap_request(apdu.data, apdu.lc, &ctap_resp); + request_from_nfc(false); if (!WTX_off()) return; From 24a006068d93b3fa7cda1cb8d2129de1a64d37d3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 5 Jul 2019 12:25:46 +0300 Subject: [PATCH 17/24] fix extended apdu decode --- fido2/apdu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fido2/apdu.c b/fido2/apdu.c index 3eacdefe..df890999 100644 --- a/fido2/apdu.c +++ b/fido2/apdu.c @@ -77,6 +77,7 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) if (len == 7U + extlen) { apdu->case_type = 0x13; + apdu->extended_apdu = true; apdu->lc = extlen; } @@ -84,6 +85,7 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) if (len == 7U + extlen + 2U) { apdu->case_type = 0x14; + apdu->extended_apdu = true; apdu->lc = extlen; apdu->le = (data[len - 2] << 8) + data[len - 1]; if (!apdu->le) @@ -94,6 +96,7 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) if (len == 7U + extlen + 3U && data[len - 3] == 0) { apdu->case_type = 0x24; + apdu->extended_apdu = true; apdu->lc = extlen; apdu->le = (data[len - 2] << 8) + data[len - 1]; if (!apdu->le) From ed9689435d7a2c7309c3b03ad9b165fbdf72315d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 5 Jul 2019 12:33:23 +0300 Subject: [PATCH 18/24] APDU_FIDO_U2F_VERSION --- targets/stm32l432/src/nfc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 2c1b34dc..520e8dd1 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -530,7 +530,8 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC, "U2F GetVersion command.\r\n"); - nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); + u2f_request_nfc(&buf[block_offset], apdu.data, apdu.lc, &ctap_resp); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); break; case APDU_FIDO_U2F_REGISTER: From fa9408d5d63b87a9bb34c17bf3df781752c10e5f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 5 Jul 2019 12:39:32 +0300 Subject: [PATCH 19/24] fix u2f tests --- tools/testing/tests/u2f.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/tests/u2f.py b/tools/testing/tests/u2f.py index d1e80331..367ee4a0 100644 --- a/tools/testing/tests/u2f.py +++ b/tools/testing/tests/u2f.py @@ -42,12 +42,14 @@ def test_u2f(self,): with Test("Check bad INS"): try: self.ctap1.send_apdu(0, 0, 0, 0, b"") + assert False except ApduError as e: assert e.code == 0x6D00 with Test("Check bad CLA"): try: self.ctap1.send_apdu(1, CTAP1.INS.VERSION, 0, 0, b"abc") + assert False except ApduError as e: assert e.code == 0x6E00 From 533ce3923785774e467c09585723b7b3693a9dc4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 6 Jul 2019 00:15:21 +0300 Subject: [PATCH 20/24] fix nfc_cc length --- targets/stm32l432/src/nfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 520e8dd1..4a7429d9 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -637,8 +637,8 @@ void nfc_process_iblock(uint8_t * buf, int len) { case APP_CAPABILITY_CONTAINER: printf1(TAG_NFC,"APP_CAPABILITY_CONTAINER\r\n"); - if (reslen == 0 || reslen > sizeof(NFC_CC) - 1) - reslen = sizeof(NFC_CC) - 1; + if (reslen == 0 || reslen > sizeof(NFC_CC)) + reslen = sizeof(NFC_CC); nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, reslen, SW_SUCCESS); ams_wait_for_tx(10); break; From 89e00482e4b6a62dbeb2e97214500f2e84ab2f37 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 6 Jul 2019 12:52:23 +0300 Subject: [PATCH 21/24] some improvements --- targets/stm32l432/src/nfc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 4a7429d9..609b1046 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -122,6 +122,7 @@ bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, i while (tstart + timeout_ms > millis()) { uint8_t int0 = ams_read_reg(AMS_REG_INT0); + if (int0) process_int0(int0); uint8_t buffer_status2 = ams_read_reg(AMS_REG_BUF2); if (buffer_status2 && (int0 & AMS_INT_RXE)) @@ -389,7 +390,12 @@ int answer_rats(uint8_t parameter) nfc_write_frame(res, sizeof(res)); - ams_wait_for_tx(10); + if (!ams_wait_for_tx(10)) + { + printf1(TAG_NFC, "RATS TX timeout.\r\n"); + ams_write_command(AMS_CMD_DEFAULT); + return 1; + } return 0; From a1eedc004893e94ec5a81ad82f50bfc5f7a35041 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 6 Jul 2019 13:09:19 +0300 Subject: [PATCH 22/24] small fix --- targets/stm32l432/src/nfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 609b1046..a2233787 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -244,7 +244,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) break; } - uint8_t rblock_offset = p14443_block_offset(res[0]); + uint8_t rblock_offset = p14443_block_offset(recbuf[0]); if (reclen != rblock_offset) { printf1(TAG_NFC, "R block length error. len: %d. %d/%d \r\n", reclen, sendlen, len); From 9e95b0075c8d2884aab2c356a3b3d8dad10723c3 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 8 Jul 2019 21:54:36 -0400 Subject: [PATCH 23/24] default no serial printing --- targets/stm32l432/src/app.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index 3bcfac2b..308e5f60 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -31,7 +31,7 @@ // #define DISABLE_CTAPHID_WINK // #define DISABLE_CTAPHID_CBOR -#define ENABLE_SERIAL_PRINTING +// #define ENABLE_SERIAL_PRINTING #if defined(SOLO_HACKER) #define SOLO_PRODUCT_NAME "Solo Hacker " SOLO_VERSION From 10bf4242e1e52dadf3f8ee8aa34f978897a95fa1 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 8 Jul 2019 21:54:48 -0400 Subject: [PATCH 24/24] fail with more import related info --- tools/testing/tests/tester.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/testing/tests/tester.py b/tools/testing/tests/tester.py index ab7c2790..a99dda5f 100644 --- a/tools/testing/tests/tester.py +++ b/tools/testing/tests/tester.py @@ -73,14 +73,12 @@ def find_device(self, nfcInterfaceOnly=False): dev = next(CtapHidDevice.list_devices(), None) if not dev: - try: - from fido2.pcsc import CtapPcscDevice + from fido2.pcsc import CtapPcscDevice + + print("--- NFC ---") + print(list(CtapPcscDevice.list_devices())) + dev = next(CtapPcscDevice.list_devices(), None) - print("--- NFC ---") - print(list(CtapPcscDevice.list_devices())) - dev = next(CtapPcscDevice.list_devices(), None) - except (ModuleNotFoundError, ImportError): - print("One of NFC library is not installed properly.") if not dev: raise RuntimeError("No FIDO device found") self.dev = dev