From 15de8dc4a6db920458c4efb29e3803e0702a260e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 25 Jan 2019 19:32:42 +0200 Subject: [PATCH] send response from key to pc in chaining mode. partially works. GetVersion must work with pc (proxmark have errors) --- targets/stm32l432/src/nfc.c | 135 +++++++++++++++++++++++++++++++++--- targets/stm32l432/src/nfc.h | 1 + 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index b4f26f0..d78b0ed 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -44,11 +44,66 @@ void nfc_state_init() void nfc_init() { - - nfc_state_init(); ams_init(); } +void process_int0(uint8_t int0) +{ + +} + +bool ams_wait_for_tx(uint32_t timeout_ms) +{ + uint32_t tstart = millis(); + while (tstart + timeout_ms > millis()) + { + uint8_t int0 = ams_read_reg(AMS_REG_INT0); + if (int0) process_int0(int0); + if (int0 & AMS_INT_TXE) + return true; + + delay(1); + } + + 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]; + *dlen = 0; + + uint32_t tstart = millis(); + while (tstart + timeout_ms > millis()) + { + uint8_t int0 = ams_read_reg(AMS_REG_INT0); + uint8_t buffer_status2 = ams_read_reg(AMS_REG_BUF2); + + if (buffer_status2 && (int0 & AMS_INT_RXE)) + { + if (buffer_status2 & AMS_BUF_INVALID) + { + printf1(TAG_NFC,"Buffer being updated!\r\n"); + } + else + { + uint8_t len = buffer_status2 & AMS_BUF_LEN_MASK; + ams_read_buffer(buf, len); + printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC, buf, len); + + *dlen = MIN(32, MIN(maxlen, len)); + memcpy(data, buf, *dlen); + + return true; + } + } + + delay(1); + } + + return false; +} void nfc_write_frame(uint8_t * data, uint8_t len) { @@ -63,11 +118,6 @@ void nfc_write_frame(uint8_t * data, uint8_t len) printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC, data, len); } -void nfc_write_response_chaining(uint8_t req0, uint8_t * data, uint8_t len) -{ - nfc_write_frame(data, len); -} - bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t resp) { uint8_t res[32]; @@ -92,6 +142,72 @@ bool nfc_write_response(uint8_t req0, uint16_t resp) return nfc_write_response_ex(req0, NULL, 0, resp); } +void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len, uint16_t resp) +{ + uint8_t res[32 + 2]; + int sendlen = 0; + uint8_t iBlock = NFC_CMD_IBLOCK | (req0 & 3); +printf1(TAG_NFC,"-- chain \r\n"); + if (len <= 32) + { + nfc_write_response_ex(req0, data, len, resp); + } else { + do { + // transmit I block + int vlen = MIN(31, len - sendlen); + res[0] = iBlock; + memcpy(&res[1], &data[sendlen], vlen); + if (vlen + sendlen < len) + { + res[0] |= 0x10; + } else { + // here may be buffer overflow!!! + res[vlen + 1] = resp >> 8; + res[vlen + 2] = resp & 0xff; + vlen += 2; + } + + nfc_write_frame(res, vlen + 1); + sendlen += vlen; + + printf1(TAG_NFC,"-- slen: %d res0: %02x\r\n", sendlen, res[0]); + + // wait for transmit (32 bytes aprox 2,5ms) + if (!ams_wait_for_tx(10)) + { + printf1(TAG_NFC, "TX timeout. slen: %d \r\n", sendlen); + break; + } + + // receive R block + if (res[0] & 0x10) + { + uint8_t recbuf[32] = {0}; + int reclen; + if (!ams_receive_with_timeout(100, recbuf, sizeof(recbuf), &reclen)) + { + printf1(TAG_NFC, "R block RX timeout.\r\n"); + break; + } + + if (reclen != 1) + { + printf1(TAG_NFC, "R block length error. len: %d \r\n", reclen); + break; + } + + if (((recbuf[0] & 0x01) != (res[0] & 1)) && ((recbuf[0] & 0xf6) == 0xa2)) + { + printf1(TAG_NFC, "R block error. txdata: %02x rxdata: %02x \r\n", res[0], recbuf[0]); + //break; + } + } + + iBlock ^= 0x01; + } while (sendlen < len); + } +} + int answer_rats(uint8_t parameter) { @@ -226,7 +342,7 @@ void nfc_process_iblock(uint8_t * buf, int len) if (status == CTAP1_ERR_SUCCESS) { - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, SW_SUCCESS); } else { nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION | status); } @@ -329,6 +445,9 @@ void nfc_loop() { t1 = millis(); read_reg_block(&ams); + + process_int0(ams.regs.int0); + // if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0) // { // printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index d80155a..16257a7 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -67,6 +67,7 @@ typedef enum } APPLETS; #define SW_SUCCESS 0x9000 +#define SW_GET_RESPONSE 0x6100 //Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. #define SW_COND_USE_NOT_SATISFIED 0x6985 #define SW_FILE_NOT_FOUND 0x6a82 #define SW_INS_INVALID 0x6d00