From 661b7bad22ac247acf184635c37591028d94a2b2 Mon Sep 17 00:00:00 2001 From: Jakub Kramarz Date: Sat, 4 Jan 2025 14:45:44 +0100 Subject: [PATCH] armsrc/sam_picopass.c: extract common routines to sam_common.c --- armsrc/Makefile | 2 +- armsrc/sam_common.c | 374 ++++++++++++++++++++++++++++++++++++++++++ armsrc/sam_common.h | 49 ++++++ armsrc/sam_mfc.c | 2 +- armsrc/sam_mfc.h | 1 + armsrc/sam_picopass.c | 175 +++++++++++--------- armsrc/sam_picopass.h | 1 + 7 files changed, 527 insertions(+), 77 deletions(-) create mode 100644 armsrc/sam_common.c create mode 100644 armsrc/sam_common.h diff --git a/armsrc/Makefile b/armsrc/Makefile index dedccd3e0..13a817dc9 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -37,7 +37,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c SRC_HF = hfops.c SRC_ISO15693 = iso15693.c iso15693tools.c -SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_mfc.c sam_seos.c +SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_common.c sam_mfc.c sam_seos.c #UNUSED: mifaresniff.c SRC_ISO14443b = iso14443b.c SRC_FELICA = felica.c diff --git a/armsrc/sam_common.c b/armsrc/sam_common.c new file mode 100644 index 000000000..5c0acbe86 --- /dev/null +++ b/armsrc/sam_common.c @@ -0,0 +1,374 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// Routines to support MFC <-> SAM communication +//----------------------------------------------------------------------------- + + +#include +// #include "sam_picopass.h" +#include "sam_common.h" +#include "iclass.h" +// #include "crc16.h" +#include "proxmark3_arm.h" +#include "BigBuf.h" +// #include "cmd.h" +#include "commonutil.h" +#include "ticks.h" +#include "dbprint.h" +#include "i2c.h" +#include "iso15693.h" +#include "protocols.h" +// #include "optimized_cipher.h" +// #include "fpgaloader.h" + +/** + * @brief Transmits data to and receives data from a HID®'s iCLASS® SE™ Processor. + * + * This function sends a specified number of bytes to the SAM and receives a response. + * + * @param data Pointer to the data to be transmitted. + * @param n Number of bytes to be transmitted. + * @param resp Pointer to the buffer where the response will be stored. + * @param resplen Pointer to the variable where the length of the response will be stored. + * @return Status code indicating success or failure of the operation. + */ +int sam_rxtx(const uint8_t *data, uint16_t n, uint8_t *resp, uint16_t *resplen) { + bool res = I2C_BufferWrite(data, n, I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN); + if (res == false) { + DbpString("failed to send to SIM CARD"); + goto out; + } + + *resplen = ISO7816_MAX_FRAME; + + res = sc_rx_bytes(resp, resplen, SIM_WAIT_DELAY); + if (res == false) { + DbpString("failed to receive from SIM CARD"); + goto out; + } + + if (*resplen < 2) { + DbpString("received too few bytes from SIM CARD"); + res = false; + goto out; + } + + uint16_t more_len = 0; + + if (resp[*resplen - 2] == 0x61 || resp[*resplen - 2] == 0x9F) { + more_len = resp[*resplen - 1]; + } else { + // we done, return + goto out; + } + + // Don't discard data we already received except the SW code. + // If we only received 1 byte, this is the echo of INS, we discard it. + *resplen -= 2; + if (*resplen == 1) { + *resplen = 0; + } + + uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, more_len}; + + res = I2C_BufferWrite(cmd_getresp, sizeof(cmd_getresp), I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN); + if (res == false) { + DbpString("failed to send to SIM CARD 2"); + goto out; + } + + more_len = 255 - *resplen; + + res = sc_rx_bytes(resp + *resplen, &more_len, SIM_WAIT_DELAY); + if (res == false) { + DbpString("failed to receive from SIM CARD 2"); + goto out; + } + + *resplen += more_len; + + out: + return res; +} + + +static inline void swap_clock_counters(volatile unsigned int * a, unsigned int * b){ + unsigned int c = *a; + *a = *b; + *b = c; +} + +/** + * @brief Swaps the timer counter values. + * + * AT91SAM7S512 has a single Timer-Counter, that is reused in clocks Ticks + * and CountSspClk. This function stops the current clock and restores previous + * values. It is used to switch between different clock sources. + * It probably makes communication timing off, but at least makes it work. + */ +static void swap_clocks(void){ + static unsigned int tc0, tc1, tc2 = 0; + StopTicks(); + swap_clock_counters(&(AT91C_BASE_TC0->TC_CV), &tc0); + swap_clock_counters(&(AT91C_BASE_TC1->TC_CV), &tc1); + swap_clock_counters(&(AT91C_BASE_TC2->TC_CV), &tc2); +} + +void switch_clock_to_ticks(void){ + swap_clocks(); + StartTicks(); +} + +void switch_clock_to_countsspclk(void){ + swap_clocks(); + StartCountSspClk(); +} + + +/** + * @brief Sends a payload to the SAM + * + * This function prepends the payload with the necessary APDU and application + * headers and sends it to the SAM. + * + * @param addr_src 0x14 for command from NFC, 0x44 for command from application + * @param addr_dest 0x0A for command to SAM + * @param addr_reply same as add_src or 0x00 if no reply is expected + * @param payload Pointer to the data to be sent. + * @param payload_len Length of the data to be sent. + * @param response Pointer to the buffer where the response will be stored. + * @param response_len Pointer to the variable where the length of the response will be stored. + * @param length Length of the data to be sent. + * @return Status code indicating success or failure of the operation. + */ +int sam_send_payload( + uint8_t addr_src, + uint8_t addr_dest, + uint8_t addr_reply, + + uint8_t *payload, + uint16_t *payload_len, + + uint8_t *response, + uint16_t *response_len +){ + int res = PM3_SUCCESS; + + uint8_t * buf = response; + + buf[0] = 0xA0; // CLA + buf[1] = 0xDA; // INS (PUT DATA) + buf[2] = 0x02; // P1 (TLV format?) + buf[3] = 0x63; // P2 + buf[4] = SAM_TX_ASN1_PREFIX_LENGTH + (uint8_t) *payload_len; // LEN + + buf[5] = addr_src; + buf[6] = addr_dest; + buf[7] = addr_reply; + + buf[8] = 0x00; + buf[9] = 0x00; + buf[10] = 0x00; + + memcpy( + &buf[11], + payload, + *payload_len + ); + + uint16_t length = SAM_TX_ASN1_PREFIX_LENGTH + SAM_TX_APDU_PREFIX_LENGTH + (uint8_t) *payload_len; + + LogTrace(buf, length, 0, 0, NULL, true); + if (g_dbglevel >= DBG_INFO){ + DbpString("SAM REQUEST APDU: "); + Dbhexdump(length, buf, false); + } + + if (sam_rxtx(buf, length, response, response_len) == false) { + if (g_dbglevel >= DBG_ERROR) + DbpString("SAM ERROR"); + res = PM3_ECARDEXCHANGE; + goto out; + } + + LogTrace(response, *response_len, 0, 0, NULL, false); + if (g_dbglevel >= DBG_INFO){ + DbpString("SAM RESPONSE APDU: "); + Dbhexdump(*response_len, response, false); + } + + out: + return res; +} + + +/** + * @brief Retreives SAM firmware version. + * + * Used just as ping or sanity check here. + * + * @return Status code indicating success or failure of the operation. + */ +int sam_get_version(void){ + int res = PM3_SUCCESS; + + if (g_dbglevel >= DBG_DEBUG) + DbpString("start sam_get_version"); + + uint8_t * response = BigBuf_malloc(ISO7816_MAX_FRAME); + uint16_t response_len = ISO7816_MAX_FRAME; + + uint8_t payload[] = { + 0xa0, 0x02, // <- SAM command + 0x82, 0x00 // <- get version + }; + uint16_t payload_len = sizeof(payload); + + sam_send_payload( + 0x44, 0x0a, 0x44, + payload, + &payload_len, + response, + &response_len + ); + + // resp: + // c1 64 00 00 00 + // bd 11 <- SAM response + // 8a 0f <- get version response + // 80 02 + // 01 29 <- version + // 81 06 + // 68 3d 05 20 26 b6 <- build ID + // 82 01 + // 01 + // 90 00 + if (g_dbglevel >= DBG_DEBUG) + DbpString("end sam_get_version"); + + if(response[5] != 0xbd){ + Dbprintf("Invalid SAM response"); + goto error; + }else{ + uint8_t * sam_response_an = sam_find_asn1_node(response + 5, 0x8a); + if(sam_response_an == NULL){ + if (g_dbglevel >= DBG_ERROR) + DbpString("SAM get response failed"); + goto error; + } + uint8_t * sam_version_an = sam_find_asn1_node(sam_response_an, 0x80); + if(sam_version_an == NULL){ + if (g_dbglevel >= DBG_ERROR) + DbpString("SAM get version failed"); + goto error; + } + uint8_t * sam_build_an = sam_find_asn1_node(sam_response_an, 0x81); + if(sam_build_an == NULL){ + if (g_dbglevel >= DBG_ERROR) + DbpString("SAM get firmware ID failed"); + goto error; + } + if (g_dbglevel >= DBG_INFO){ + DbpString("SAM get version successful"); + Dbprintf("Firmware version: %X.%X", sam_version_an[2], sam_version_an[3]); + Dbprintf("Firmware ID: "); + Dbhexdump(sam_build_an[1], sam_build_an+2, false); + } + goto out; + } + + error: + res = PM3_ESOFT; + + out: + BigBuf_free(); + + if (g_dbglevel >= DBG_DEBUG) + DbpString("end sam_get_version"); + + return res; +} + + + +/** + * @brief Finds an ASN.1 node of a specified type within a given root node. + * + * This function searches through a single level of the ASN.1 structure starting + * from the root node to find a node of the specified type. + * + * @param root Pointer to the root node of the ASN.1 structure. + * @param type The type of the ASN.1 node to find. + * @return Pointer to the ASN.1 node of the specified type if found, otherwise NULL. + */ +uint8_t * sam_find_asn1_node(uint8_t * root, const uint8_t type){ + const uint8_t * end = root + *(root+1); + uint8_t * current = root + 2; + while(current < end){ + if(*current == type){ + return current; + }else{ + current += 2 + *(current+1); + } + } + return NULL; +} + +// /** +// * @brief Appends an ASN.1 node to the end of a given node. +// * +// * This function appends an ASN.1 node of a specified type and length to the end of +// * the ASN.1 structure at specified node level. +// * It would make the code cleaner, but I can't get it to work - it calculates fields lengths incorrectly. +// * +// * @param root Pointer to the root node of the ASN.1 structure. +// * @param root Pointer to the node to be appended of the ASN.1 structure. +// * @param type The type of the ASN.1 node to append. +// * @param data Pointer to the data to be appended. +// * @param len The length of the data to be appended. +// */ +// void sam_append_asn1_node(uint8_t * root, uint8_t * node, uint8_t type, uint8_t * data, uint8_t len){ +// uint8_t * end = root + *(root+1); + +// *(end) = type; +// *(end+1) = len; +// memcpy(end+2, data, len); + +// for(uint8_t * current = root; current < node; current += 2){ +// *(current+1) += 2 + len; +// }; +// return; +// } + +void sam_send_ack(void){ + uint8_t * response = BigBuf_malloc(ISO7816_MAX_FRAME); + uint16_t response_len = ISO7816_MAX_FRAME; + + uint8_t payload[] = { + 0xa0, 0 + }; + uint16_t payload_len = sizeof(payload); + + sam_send_payload( + 0x44, 0x0a, 0x00, + payload, + &payload_len, + response, + &response_len + ); + + BigBuf_free(); +} diff --git a/armsrc/sam_common.h b/armsrc/sam_common.h new file mode 100644 index 000000000..5aa0fe04d --- /dev/null +++ b/armsrc/sam_common.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +#ifndef __SAM_COMMON_H +#define __SAM_COMMON_H + +#include "common.h" + +static const uint8_t SAM_TX_APDU_PREFIX_LENGTH = 5; +static const uint8_t SAM_TX_ASN1_PREFIX_LENGTH = 6; +static const uint8_t SAM_RX_ASN1_PREFIX_LENGTH = 5; + +int sam_rxtx(const uint8_t *data, uint16_t n, uint8_t *resp, uint16_t *resplen); + +void switch_clock_to_ticks(void); +void switch_clock_to_countsspclk(void); + +int sam_send_payload( + uint8_t addr_src, + uint8_t addr_dest, + uint8_t addr_reply, + + uint8_t *payload, + uint16_t *payload_len, + + uint8_t *response, + uint16_t *response_len +); + +int sam_get_version(void); + +uint8_t * sam_find_asn1_node(uint8_t * root, const uint8_t type); +//void sam_append_asn1_node(uint8_t * root, uint8_t * node, uint8_t type, uint8_t * data, uint8_t len); + +void sam_send_ack(void); + +#endif diff --git a/armsrc/sam_mfc.c b/armsrc/sam_mfc.c index 090f4a781..5e2309437 100644 --- a/armsrc/sam_mfc.c +++ b/armsrc/sam_mfc.c @@ -16,7 +16,7 @@ // Routines to support MFC <-> SAM communication //----------------------------------------------------------------------------- #include "sam_mfc.h" -#include "sam_seos.h" +#include "sam_common.h" #include "iclass.h" #include "proxmark3_arm.h" diff --git a/armsrc/sam_mfc.h b/armsrc/sam_mfc.h index 5cf55d711..527bc77ff 100644 --- a/armsrc/sam_mfc.h +++ b/armsrc/sam_mfc.h @@ -17,5 +17,6 @@ #define __SAM_MFC_H #include "common.h" +#include "sam_common.h" #endif diff --git a/armsrc/sam_picopass.c b/armsrc/sam_picopass.c index fd465c992..882f03b9d 100644 --- a/armsrc/sam_picopass.c +++ b/armsrc/sam_picopass.c @@ -16,6 +16,7 @@ // Routines to support Picopass <-> SAM communication //----------------------------------------------------------------------------- #include "sam_picopass.h" +#include "sam_common.h" #include "iclass.h" #include "crc16.h" #include "proxmark3_arm.h" @@ -30,66 +31,79 @@ #include "optimized_cipher.h" #include "fpgaloader.h" -static int sam_rxtx(const uint8_t *data, uint16_t n, uint8_t *resp, uint16_t *resplen) { - StartTicks(); +/** + * @brief Sets the card detected status for the SAM (Secure Access Module). + * + * This function informs that a card has been detected by the reader and + * initializes SAM communication with the card. + * + * @param card_select Pointer to the descriptor of the detected card. + * @return Status code indicating success or failure of the operation. + */ +static int sam_set_card_detected(picopass_hdr_t * card_select){ + int res = PM3_SUCCESS; + if (g_dbglevel >= DBG_DEBUG) + DbpString("start sam_set_card_detected"); - bool res = I2C_BufferWrite(data, n, I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN); - if (res == false) { - DbpString("failed to send to SIM CARD"); + uint8_t * response = BigBuf_malloc(ISO7816_MAX_FRAME); + uint16_t response_len = ISO7816_MAX_FRAME; + + // a0 12 + // ad 10 + // a0 0e + // 80 02 + // 00 04 <- Picopass + // 81 08 + // 9b fc a4 00 fb ff 12 e0 <- CSN + + uint8_t payload[] = { + 0xa0, 18, // <- SAM command + 0xad, 16, // <- set detected card + 0xa0, 4+10, + 0x80, 2, // <- protocol + 0x00, 0x04, // <- Picopass + 0x81, 8, // <- CSN + card_select->csn[0], card_select->csn[1], card_select->csn[2], card_select->csn[3], + card_select->csn[4], card_select->csn[5], card_select->csn[6], card_select->csn[7] + }; + uint16_t payload_len = sizeof(payload); + + sam_send_payload( + 0x44, 0x0a, 0x44, + payload, + &payload_len, + response, + &response_len + ); + + // resp: + // c1 64 00 00 00 + // bd 02 <- response + // 8a 00 <- empty response (accepted) + // 90 00 + + if(response[5] != 0xbd){ + if (g_dbglevel >= DBG_ERROR) + Dbprintf("Invalid SAM response"); + goto error; + }else{ + // uint8_t * sam_response_an = sam_find_asn1_node(response + 5, 0x8a); + // if(sam_response_an == NULL){ + // if (g_dbglevel >= DBG_ERROR) + // Dbprintf("Invalid SAM response"); + // goto error; + // } goto out; } + error: + res = PM3_ESOFT; - *resplen = ISO7816_MAX_FRAME; + out: + BigBuf_free(); - res = sc_rx_bytes(resp, resplen, SIM_WAIT_DELAY); - if (res == false) { - DbpString("failed to receive from SIM CARD"); - goto out; - } - - if (*resplen < 2) { - DbpString("received too few bytes from SIM CARD"); - res = false; - goto out; - } - - uint16_t more_len = 0; - - if (resp[*resplen - 2] == 0x61 || resp[*resplen - 2] == 0x9F) { - more_len = resp[*resplen - 1]; - } else { - // we done, return - goto out; - } - - // Don't discard data we already received except the SW code. - // If we only received 1 byte, this is the echo of INS, we discard it. - *resplen -= 2; - if (*resplen == 1) { - *resplen = 0; - } - - uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, more_len}; - - res = I2C_BufferWrite(cmd_getresp, sizeof(cmd_getresp), I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN); - if (res == false) { - DbpString("failed to send to SIM CARD 2"); - goto out; - } - - more_len = 255 - *resplen; - - res = sc_rx_bytes(resp + *resplen, &more_len, SIM_WAIT_DELAY); - if (res == false) { - DbpString("failed to receive from SIM CARD 2"); - goto out; - } - - *resplen += more_len; - -out: - StopTicks(); + if (g_dbglevel >= DBG_DEBUG) + DbpString("end sam_set_card_detected"); return res; } @@ -218,23 +232,19 @@ int sam_picopass_get_pacs(void) { uint8_t *sam_apdu = BigBuf_calloc(ISO7816_MAX_FRAME); // ----------------------------------------------------------------------------- - // first - // a0 da 02 63 1a 44 0a 44 00 00 00 a0 12 ad 10 a0 0e 80 02 00 04 81 08 9b fc a4 00 fb ff 12 e0 - hexstr_to_byte_array("a0da02631a440a44000000a012ad10a00e800200048108", sam_apdu, &sam_len); - memcpy(sam_apdu + sam_len, hdr.csn, sizeof(hdr.csn)); - sam_len += sizeof(hdr.csn); - - if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) { - res = PM3_ECARDEXCHANGE; - goto out; - } - print_dbg("-- 1", resp, resp_len); + // first - set detected card (0xAD) + switch_clock_to_ticks(); + sam_set_card_detected(&hdr); // ----------------------------------------------------------------------------- - // second - // a0 da 02 63 0d 44 0a 44 00 00 00 a0 05 a1 03 80 01 04 - hexstr_to_byte_array("a0da02630d440a44000000a005a103800104", sam_apdu, &sam_len); - if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) { + // second - get PACS (0xA1) + + // a0 05 + // a1 03 + // 80 01 + // 04 + hexstr_to_byte_array("a005a103800104", sam_apdu, &sam_len); + if(sam_send_payload(0x44, 0x0a, 0x44, sam_apdu, &sam_len, resp, &resp_len) != PM3_SUCCESS) { res = PM3_ECARDEXCHANGE; goto out; } @@ -245,7 +255,7 @@ int sam_picopass_get_pacs(void) { // Tag|c00a140a000000a110a10e8004 0c05de64 8102 0004 820201f4 // ----------------------------------------------------------------------------- - // third AIA block 5 + // third AIA block 5 (emulated tag <-> SAM exchange starts here) // a0da02631c140a00000000bd14a012a010800a ffffff0006fffffff88e 81020000 // picopass legacy is fixed. wants AIA and crc. ff ff ff ff ff ff ff ff ea f5 // picpoasss SE ff ff ff 00 06 ff ff ff f8 8e @@ -300,7 +310,7 @@ int sam_picopass_get_pacs(void) { } // start ssp clock again... - StartCountSspClk(); + switch_clock_to_countsspclk(); // NOW we auth against tag uint8_t cmd_check[9] = { ICLASS_CMD_CHECK }; @@ -325,6 +335,7 @@ int sam_picopass_get_pacs(void) { hexstr_to_byte_array("A0DA026316140A00000000BD0EA00CA00A8004311E32E981020000", sam_apdu, &sam_len); memcpy(sam_apdu + 19, mac, sizeof(mac)); + switch_clock_to_ticks(); if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) { res = PM3_ECARDEXCHANGE; goto out; @@ -355,7 +366,7 @@ int sam_picopass_get_pacs(void) { // c1 61 c1 00 00 a1 10 a1 0e 80 04 0c 06 45 56 81 02 00 04 82 02 01 f4 90 00 // read block 6 - StartCountSspClk(); + switch_clock_to_countsspclk(); start_time = GetCountSspClk(); iclass_send_as_reader(resp + 11, 4, &start_time, &eof_time, shallow_mod); @@ -373,6 +384,7 @@ int sam_picopass_get_pacs(void) { hexstr_to_byte_array("A0DA02631C140A00000000BD14A012A010800A030303030003E017432381020000", sam_apdu, &sam_len); memcpy(sam_apdu + 19, resp, resp_len); + switch_clock_to_ticks(); if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) { res = PM3_ECARDEXCHANGE; goto out; @@ -382,7 +394,7 @@ int sam_picopass_get_pacs(void) { // c161c10000a110a10e8004 0606455681020004820201f49000 // read the credential blocks - StartCountSspClk(); + switch_clock_to_countsspclk(); start_time = GetCountSspClk(); iclass_send_as_reader(resp + 11, 4, &start_time, &eof_time, shallow_mod); @@ -400,6 +412,7 @@ int sam_picopass_get_pacs(void) { hexstr_to_byte_array("A0DA026334140A00000000BD2CA02AA0288022030303030003E017769CB4A198E0DEC82AD4C8211F9968712BE7393CF8E71D7E804C81020000", sam_apdu, &sam_len); memcpy(sam_apdu + 19, resp, resp_len); + switch_clock_to_ticks(); if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) { res = PM3_ECARDEXCHANGE; goto out; @@ -409,7 +422,13 @@ int sam_picopass_get_pacs(void) { // ----------------------------------------------------------------------------- // TEN ask for PACS data - // A0DA02630C440A00000000BD04A0028200 + // A0 DA 02 63 0C + // 44 0A 00 00 00 00 + // BD 04 + // A0 02 + // 82 00 + + // (emulated tag <-> SAM exchange ends here) hexstr_to_byte_array("A0DA02630C440A00000000BD04A0028200", sam_apdu, &sam_len); memcpy(sam_apdu + 19, resp, resp_len); @@ -424,7 +443,12 @@ int sam_picopass_get_pacs(void) { goto out; } - // c164000000bd098a07 030506951f9a00 9000 + // resp: + // c1 64 00 00 00 + // bd 09 + // 8a 07 + // 03 05 06 95 1f 9a 00 <- decoded PACS data + // 90 00 uint8_t *pacs = BigBuf_calloc(resp[8]); memcpy(pacs, resp + 9, resp[8]); @@ -439,6 +463,7 @@ out: off: switch_off(); + StopTicks(); BigBuf_free(); return res; } diff --git a/armsrc/sam_picopass.h b/armsrc/sam_picopass.h index 7feef0bde..26d734d39 100644 --- a/armsrc/sam_picopass.h +++ b/armsrc/sam_picopass.h @@ -17,6 +17,7 @@ #define __SAM_PICOPASS_H #include "common.h" +#include "sam_common.h" int sam_picopass_get_pacs(void);