From e996d470f9c5e2815a00b1b4988099177caeffd8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 19:15:48 +0200 Subject: [PATCH 1/9] small fixes --- targets/stm32l432/src/nfc.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 0b34d34..f98d53a 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -341,12 +341,22 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_U2F_VERSION: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + printf1(TAG_NFC, "U2F GetVersion command.\r\n"); nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); break; case APDU_FIDO_U2F_REGISTER: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + printf1(TAG_NFC, "U2F Register command.\r\n"); if (plen != 64) @@ -366,6 +376,11 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_U2F_AUTHENTICATE: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + printf1(TAG_NFC, "U2F Authenticate command.\r\n"); if (plen != 64 + 1 + buf[6 + 64]) @@ -386,6 +401,11 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_NFCCTAP_MSG: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + t1 = millis(); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); @@ -421,7 +441,7 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); plen = 15; } - nfc_write_response_ex(buf[0], &NFC_CC, plen, SW_SUCCESS); + nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, plen, SW_SUCCESS); ams_wait_for_tx(10); break; case APP_NDEF_TAG: @@ -450,10 +470,17 @@ void nfc_process_iblock(uint8_t * buf, int len) } +static uint8_t ibuf[1024]; +static int ibuflen = 0; + +void clear_ibuf() +{ + ibuflen = 0; + memset(ibuf, 0, sizeof(ibuf)); +} + void nfc_process_block(uint8_t * buf, int len) { - static uint8_t ibuf[1024]; - static int ibuflen = 0; if (!len) return; @@ -509,7 +536,7 @@ void nfc_process_block(uint8_t * buf, int len) // printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); nfc_process_iblock(buf, len); } - ibuflen = 0; + clear_ibuf(); } } else if (IS_RBLOCK(buf[0])) @@ -527,6 +554,7 @@ void nfc_process_block(uint8_t * buf, int len) ams_wait_for_tx(2); ams_write_command(AMS_CMD_SLEEP); nfc_state_init(); + clear_ibuf(); } else { @@ -610,6 +638,7 @@ void nfc_loop() t1 = millis(); answer_rats(buf[1]); NFC_STATE.block_num = 1; + clear_ibuf(); printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: From 5c8acdd66607f6f464f7f4bcbf16dffc926730e8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 20:00:13 +0200 Subject: [PATCH 2/9] fix u2f user presence check, added `dont-enforce-user-presence-and-sign`, fix counter --- fido2/u2f.c | 29 ++++++++++++++++++----------- fido2/u2f.h | 1 + 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/fido2/u2f.c b/fido2/u2f.c index edc4451..1eb7e60 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -233,8 +233,8 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c } } if ( - control != U2F_AUTHENTICATE_SIGN || - req->khl != U2F_KEY_HANDLE_SIZE || + (control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) || + req->khl != U2F_KEY_HANDLE_SIZE || u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important u2f_load_key(&req->kh, req->app) != 0 @@ -243,9 +243,11 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c return U2F_SW_WRONG_PAYLOAD; } + // dont-enforce-user-presence-and-sign + if (control == U2F_AUTHENTICATE_SIGN_NO_USER) + up = 0; - - if(!fromNFC) + if(!fromNFC && up) { if (ctap_user_presence_test() == 0) { @@ -254,21 +256,26 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c } count = ctap_atomic_count(0); + uint8_t vcount[4]; + vcount[3] = (count) & 0xff; + vcount[2] = (count >> 8) & 0xff; + vcount[1] = (count >> 16) & 0xff; + vcount[0] = (count >> 24) & 0xff; crypto_sha256_init(); - crypto_sha256_update(req->app,32); - crypto_sha256_update(&up,1); - crypto_sha256_update((uint8_t *)&count,4); - crypto_sha256_update(req->chal,32); + crypto_sha256_update(req->app, 32); + crypto_sha256_update(&up, 1); + crypto_sha256_update(vcount, 4); + crypto_sha256_update(req->chal, 32); crypto_sha256_final(hash); - printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F,hash,32); + printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F, hash, 32); crypto_ecc256_sign(hash, 32, sig); - u2f_response_writeback(&up,1); - u2f_response_writeback((uint8_t *)&count,4); + u2f_response_writeback(&up, 1); + u2f_response_writeback(vcount, 4); dump_signature_der(sig); return U2F_SW_NO_ERROR; diff --git a/fido2/u2f.h b/fido2/u2f.h index 3f4f689..88975a1 100644 --- a/fido2/u2f.h +++ b/fido2/u2f.h @@ -53,6 +53,7 @@ // U2F Authenticate #define U2F_AUTHENTICATE_CHECK 0x7 #define U2F_AUTHENTICATE_SIGN 0x3 +#define U2F_AUTHENTICATE_SIGN_NO_USER 0x8 // Command status responses From f6e2bfa6837ccec165c623ad50c027ffa10aca68 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 20:06:19 +0200 Subject: [PATCH 3/9] yubikey answers U2F_SW_WRONG_PAYLOAD instead of U2F_SW_WRONG_DATA --- fido2/u2f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fido2/u2f.c b/fido2/u2f.c index 1eb7e60..ac84205 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -229,7 +229,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c } else { - return U2F_SW_WRONG_DATA; + return U2F_SW_WRONG_PAYLOAD; } } if ( From 0ef42b2df716fdb5d5845f18804d38945bc3b846 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 20:45:36 +0200 Subject: [PATCH 4/9] added WTX sending sketch --- targets/stm32l432/src/nfc.c | 21 +++++++++++++++++++++ targets/stm32l432/src/nfc.h | 3 +++ 2 files changed, 24 insertions(+) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index f98d53a..fc9ed3c 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -54,6 +54,21 @@ void process_int0(uint8_t int0) } +// WTX on/off: +// sends/receives WTX frame to reader every `WTX_time` time in ms +// works via timer interrupts +// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> +bool WTX_on(int WTX_time) +{ + return true; +} + +bool WTX_off() +{ + return true; +} + + bool ams_wait_for_tx(uint32_t timeout_ms) { uint32_t tstart = millis(); @@ -367,7 +382,9 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); + WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); + WTX_off(); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -392,7 +409,9 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); + WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); + WTX_off(); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); @@ -409,8 +428,10 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); + WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); + WTX_off(); printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index b66b43e..4859570 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -20,6 +20,9 @@ typedef struct uint8_t tlv[8]; } __attribute__((packed)) CAPABILITY_CONTAINER; +// WTX time in ms +#define WTX_TIME_DEFAULT 300 + #define NFC_CMD_REQA 0x26 #define NFC_CMD_WUPA 0x52 #define NFC_CMD_HLTA 0x50 From ab01d0c73dd493dbb06c234cb60180fab0ed6f80 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:02:02 +0200 Subject: [PATCH 5/9] delete comment --- targets/stm32l432/src/nfc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index fc9ed3c..bfa8a87 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -68,7 +68,6 @@ bool WTX_off() return true; } - bool ams_wait_for_tx(uint32_t timeout_ms) { uint32_t tstart = millis(); @@ -85,7 +84,6 @@ bool ams_wait_for_tx(uint32_t timeout_ms) return false; } -//bool ams_receive_with_timeout(10, recbuf, sizeof(recbuf), &reclen)) bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, int *dlen) { uint8_t buf[32]; From c6daa4acc9e2ed5499533efeb7be7241a4f3e5cb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:27:43 +0200 Subject: [PATCH 6/9] more WTX sketch --- targets/stm32l432/src/nfc.c | 70 +++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index bfa8a87..c03261e 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -54,20 +54,6 @@ void process_int0(uint8_t int0) } -// WTX on/off: -// sends/receives WTX frame to reader every `WTX_time` time in ms -// works via timer interrupts -// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> -bool WTX_on(int WTX_time) -{ - return true; -} - -bool WTX_off() -{ - return true; -} - bool ams_wait_for_tx(uint32_t timeout_ms) { uint32_t tstart = millis(); @@ -223,6 +209,62 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) } } +// WTX on/off: +// sends/receives WTX frame to reader every `WTX_time` time in ms +// works via timer interrupts +// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> +static bool WTX_sent; +static bool WTX_fail; +bool WTX_on(int WTX_time) +{ + WTX_sent = false; + WTX_fail = false; + + return true; +} + +bool WTX_off() +{ + if (WTX_fail) + return false; + + return true; +} + +// executes twice a period. 1st for send WTX, 2nd for check the result +bool WTX_process() +{ + uint8_t wtx[] = {0xf2, 0x01}; + if (WTX_fail) + return false; + + if (!WTX_sent) + { + nfc_write_frame(wtx, sizeof(wtx)); + WTX_sent = true; + return true; + } + else + { + uint8_t data[32]; + int len; + if (ams_receive_with_timeout(0, data, sizeof(data), &len)) + { + WTX_fail = true; + return false; + } + + if (len != 2 || data[0] != 0xf2 || data[1] != 0x01) + { + WTX_fail = true; + return false; + } + + WTX_sent = false; + return true; + } +} + int answer_rats(uint8_t parameter) { From 6e5de7bd6b2d1942ba75b402dc8b849954287360 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:31:20 +0200 Subject: [PATCH 7/9] read data if we sent WTX --- targets/stm32l432/src/nfc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index c03261e..b1d8bf1 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -223,16 +223,26 @@ bool WTX_on(int WTX_time) return true; } +bool WTX_process(int read_timeout); + bool WTX_off() { if (WTX_fail) return false; + // read data if we sent WTX + if (WTX_sent) + { + if (!WTX_process(10)) + return false; + } + return true; } // executes twice a period. 1st for send WTX, 2nd for check the result -bool WTX_process() +// read timeout must be 0 to call from int +bool WTX_process(int read_timeout) { uint8_t wtx[] = {0xf2, 0x01}; if (WTX_fail) @@ -248,7 +258,7 @@ bool WTX_process() { uint8_t data[32]; int len; - if (ams_receive_with_timeout(0, data, sizeof(data), &len)) + if (ams_receive_with_timeout(read_timeout, data, sizeof(data), &len)) { WTX_fail = true; return false; From 429e4b2a771222ce236d27d81afbd6073e6dbdd7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:33:57 +0200 Subject: [PATCH 8/9] add WTX_clear(); --- targets/stm32l432/src/nfc.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index b1d8bf1..a7819cb 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -215,11 +215,16 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) // WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> static bool WTX_sent; static bool WTX_fail; -bool WTX_on(int WTX_time) + +void WTX_clear() { WTX_sent = false; WTX_fail = false; - +} + +bool WTX_on(int WTX_time) +{ + WTX_clear(); return true; } @@ -434,7 +439,8 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - WTX_off(); + if (!WTX_off()) + return; printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -461,7 +467,8 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - WTX_off(); + if (!WTX_off()) + return; printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); @@ -481,7 +488,8 @@ 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); - WTX_off(); + if (!WTX_off()) + return; printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) @@ -626,6 +634,7 @@ void nfc_process_block(uint8_t * buf, int len) ams_write_command(AMS_CMD_SLEEP); nfc_state_init(); clear_ibuf(); + WTX_clear(); } else { @@ -710,6 +719,7 @@ void nfc_loop() answer_rats(buf[1]); NFC_STATE.block_num = 1; clear_ibuf(); + WTX_clear(); printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: From 19627a959a8bf465c29f1e0fab8398321af8522c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:35:45 +0200 Subject: [PATCH 9/9] some TODOs --- targets/stm32l432/src/nfc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index a7819cb..eb07440 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -225,6 +225,9 @@ void WTX_clear() bool WTX_on(int WTX_time) { WTX_clear(); + + // TODO: start interrupt + return true; } @@ -232,8 +235,7 @@ bool WTX_process(int read_timeout); bool WTX_off() { - if (WTX_fail) - return false; + // TODO: stop interrupt // read data if we sent WTX if (WTX_sent) @@ -241,6 +243,9 @@ bool WTX_off() if (!WTX_process(10)) return false; } + + if (WTX_fail) + return false; return true; }