From 5be1b612f7b57e9561f857d5441695ae0f5cf3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 21 May 2018 17:51:14 +0200 Subject: [PATCH 01/30] fix: remove unused code adc2uv is not used in boardver_adc.c. a FIXME comment says it should be shared with mode_cardemu.c. the exact same code is already available in mode_cardemu.c --- firmware/libboard/common/source/boardver_adc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/firmware/libboard/common/source/boardver_adc.c b/firmware/libboard/common/source/boardver_adc.c index ca3d1fe2..1bd3b58b 100644 --- a/firmware/libboard/common/source/boardver_adc.c +++ b/firmware/libboard/common/source/boardver_adc.c @@ -1,14 +1,6 @@ #include "board.h" #include "boardver_adc.h" -/* FIXME: share this with mode_cardemu.c */ -#define UV_PER_LSB ((3300 * 1000) / 4096) -static uint32_t adc2uv(uint16_t adc) -{ - uint32_t uv = (uint32_t) adc * UV_PER_LSB; - return uv; -} - /*********************************************************************** * ADC for board version detection ***********************************************************************/ From 0471d2a39065f8e387c562ba26d20b057c305568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 21 May 2018 18:52:06 +0200 Subject: [PATCH 02/30] fix: initialize uninitialized variable in USBDFU_DFU_RequestHandler --- firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c | 2 +- firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c index 10f015b6..6230d6cd 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c @@ -217,7 +217,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) uint8_t req = USBGenericRequest_GetRequest(request); uint16_t len = USBGenericRequest_GetLength(request); uint16_t val = USBGenericRequest_GetValue(request); - int rc, ret; + int rc, ret = DFU_RET_NOTHING; TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r", USBGenericRequest_GetType(request), diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c index 177a7407..444b75f8 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c @@ -107,7 +107,7 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request) uint8_t req = USBGenericRequest_GetRequest(request); uint16_t len = USBGenericRequest_GetLength(request); uint16_t val = USBGenericRequest_GetValue(request); - int rc, ret; + int rc, ret = DFU_RET_NOTHING; TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r", USBGenericRequest_GetType(request), From fe72bf11fd79439b994fe5abb4174a171ce9861f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 21 May 2018 19:33:50 +0200 Subject: [PATCH 03/30] fix pointer casting warning fixes following warning: libboard/common/source/board_cstartup_gnu.c:137:11: warning: assignment to 'void (*)(void)' from 'unsigned int' makes pointer from integer without a cast [-Wint-conversion] appReset = pSrc[1]; --- firmware/libboard/common/source/board_cstartup_gnu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/libboard/common/source/board_cstartup_gnu.c b/firmware/libboard/common/source/board_cstartup_gnu.c index 775f3252..f2d17aff 100644 --- a/firmware/libboard/common/source/board_cstartup_gnu.c +++ b/firmware/libboard/common/source/board_cstartup_gnu.c @@ -134,7 +134,7 @@ static void BootIntoApp(void) pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE); SCB->VTOR = ((unsigned int)(pSrc)) | (0x0 << 7); - appReset = pSrc[1]; + appReset = (void(*)(void))pSrc[1]; g_dfu->state = DFU_STATE_appIDLE; From de2d03ca221c9719ce211e4842eeed2fd4dd015a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 21 May 2018 19:35:56 +0200 Subject: [PATCH 04/30] README: rewrite to better explain environment variables and point to the wiki for flashing --- firmware/README.txt | 101 ++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/firmware/README.txt b/firmware/README.txt index 9e825571..dcbafb29 100644 --- a/firmware/README.txt +++ b/firmware/README.txt @@ -1,70 +1,81 @@ +This is the source code for SIMtrace 2 firmwares. -== BOARDS += Hardware -A board defines a given circuit board, i.e. SIMtrace, OWHW, QMOD +== Micro-Controller -It defines the given hardware model for which the program is to be -compiled. +The firmware is for Microchip (formerly Atmel) ATSAM3S4B micro-controllers (MCU). +Product page: https://www.microchip.com/wwwproducts/en/ATSAM3S4B +Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-6500-32-bit-Cortex-M3-Microcontroller-SAM3S4-SAM3S2-SAM3S1_Datasheet.pdf + +Note: The SAM3S is now not recommended for new designs. +It can be replaced by the pin-compatible SAM4S. +The MCU can be specified using the environment variable `CHIP` (set to `sam3s4` per default) for future MCU support. + +== Boards + +The SIMtrace 2 firmware supports multiple boards. +A board defines a given circuit board. +While compiling the firmware, set the target board using the `BOARD` environment variable (set to `qmod` per default). +The supported boards correspond to sub-folders under `libboard`. Current boards supported are: -* simtrace: The good old Osmocom SIMtrace PCB with SAM3 instead of - SAM7, open hardware. -* qmod: A sysmocom-proprietary quad mPCIe carrier board, publicly available -* owhw: An undisclosed sysmocom-internal board, not publicly available -== APPLICATIONS +* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware. +* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available +* `owhw`: An undisclosed sysmocom-internal board, not publicly available -An application is a specific piece of software with given -functionality. += Firmware -== ENVIRONMENTS +== Library + +The firmware uses the manufacturer provided Software Package (SoftPack) micro-controller library. +The original library is available at https://www.microchip.com/design-centers/32-bit/softpacks/legacy-softpacks . +Version 2.1 from 2001 is used: http://ww1.microchip.com/downloads/en/DeviceDoc/SAM3S_softpack_2.1_for_CodeSourcery_2010q1.zip +The SIMtrace 2 project uses the `libboard_sam3s-ek`, `libchip_sam3s`, and `usb` sub-libraries, saved in `atmel_softpack_libraries` (with local modifications). + +Note: SoftPack is the legacy micro-controller library. +This library is now replaced by the Advanced Software Framework (ASF): https://www.microchip.com/avr-support/advanced-software-framework-(asf) . +The SAM3S ASF documentation is available at http://asf.atmel.com/docs/latest/sam3s/html/index.html . + +== Applications + +An application is a specific piece of software with given functionality. +While compiling the firmware, set the target application using the `APP` environment variable (set to `dfu` per default). +The supported applications correspond to sub-folder under `apps`. + +Current applications supported are: + +* `dfu`: The USB DFU bootloader to flash further main appliction firmwares. +* `ccid`: To use SIMtrace 2 as USB CCID smartcard reader. +* `cardem`: To provide remote SIM operation capabilities. +* `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace) +* `triple_play`: To support the three previous functionalities, using USB configurations. + +== Memories + +Firmwares can be run from several memory locations: -An environment is a runtime environment, typically defined by a linker -script. The current runtime environments include * flash: Run natively from start of flash memory -* dfu: Run after a DFU bootloader from an offset after the first 16k - of flash (the first 16k are reserved for the bootloader) +* dfu: Run after a DFU bootloader from an offset after the first 16k of flash (the first 16k are reserved for the bootloader) * ram: Run from within the RAM of the chip, downloaded via JTAG/SWD - == Building -A given software build is made for a specific combination of an APP -running in a certain ENVIRONMENT on a given BOARD. +A given firmware build is made for a specific combination of an application `APP` running in a certain memory `MEM` on a given board `BOARD`. +When building using `make`, set the target application using the `APP` environment variable and target board using the `BOARD` environment variable, e.g.: -A Makefile is provided. It will create output files in the format -bin/$(BOARD)-$(APP)-$(ENV).{elf,bin} - -You can specify the APP and BOARD to build when calling make, like -e.g. * make APP=cardem BOARD=qmod * make APP=dfu BOARD=qmod +The Makefile will create output files in the format: `bin/$(BOARD)-$(APP)-$(MEM).{elf,bin}` + The level of debug messages can be altered at compile time: ``` $ make TRACE_LEVEL=4 ``` Accepted values: 0 (NO_TRACE) to 5 (DEBUG) -== Flashing += Flashing -For flashing the firmware, there are at least two options. - -=== Using JTAG + OpenOCD to flash the DFU bootloader - -The first one is using openocd and a JTAG key. -For this option, a JTAG connector has to be soldered onto the board, which is not attached per default. - -``` -$ openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/$(BOARD)-dfu-flash.bin 0" -c "reset" -c "shutdown" -``` - -=== Using bossac to flash the DFU bootloader - -The second option is using rumba for flashing. No further hardware has to be provided for this option. - -FIXME - -=== Using DFU to flash application - -FIXME +To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/). From f79ae1c54a732e2834b6af8418f4a78bf1f8e422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Fri, 1 Jun 2018 11:02:49 +0200 Subject: [PATCH 05/30] dfu: fix address destination check and add stack overwrite check in USBDFU_handle_dnload During DFU download the destination start address is checked to not exceed the RAM or flash end address, but it is also necessary to check if the end of the data to be downloaded is also within the allowed range. When downloading to RAM it is also necessary to check if the data to be downloaded does not overwrite (i.e. corrupt) the stack. --- firmware/apps/dfu/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c index 01cf1e01..a90b9ac9 100644 --- a/firmware/apps/dfu/main.c +++ b/firmware/apps/dfu/main.c @@ -21,22 +21,24 @@ unsigned int g_unique_id[4]; #define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE) #define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE) -/* incoming call-back: Host has transfered 'len' bytes (stored at +/* incoming call-back: Host has transferred 'len' bytes (stored at * 'data'), which we shall write to 'offset' into the partition - * associated with 'altif'. Guaranted to be les than + * associated with 'altif'. Guaranted to be less than * BOARD_DFU_PAGE_SIZE */ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int len) { uint32_t addr; int rc; + /* address of the last allocated variable on the stack */ + uint32_t stack_addr = (uint32_t)&rc; printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len); switch (altif) { case ALTIF_RAM: addr = RAM_ADDR(offset); - if (addr > IRAM_ADDR + IRAM_SIZE) { + if (addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) { g_dfu->state = DFU_STATE_dfuERROR; g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; @@ -45,7 +47,7 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, return DFU_RET_ZLP; case ALTIF_FLASH: addr = FLASH_ADDR(offset); - if (addr > IFLASH_ADDR + IFLASH_SIZE) { + if (addr + len >= IFLASH_ADDR + IFLASH_SIZE) { g_dfu->state = DFU_STATE_dfuERROR; g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; From 7b51f72e836101386f2018ada84a05daba9075c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 4 Jun 2018 16:21:23 +0200 Subject: [PATCH 06/30] copy working cardem app to trace because the applications share the board capabilities defined in libboard/*/include/board.h and USB configurations are enabled according to the previously defined capabilities in libcommon/source.usb.c, all applications actually offer the same functions. thus creating the trace application is only mainly a cosmetic change, as the sniffer function will also be present and enabled in the cardem application. --- firmware/apps/trace/Makefile | 3 + firmware/apps/trace/main.c | 209 ++++++++++++++++++++++++++++ firmware/apps/trace/usb_strings.txt | 10 ++ 3 files changed, 222 insertions(+) create mode 100644 firmware/apps/trace/Makefile create mode 100644 firmware/apps/trace/usb_strings.txt diff --git a/firmware/apps/trace/Makefile b/firmware/apps/trace/Makefile new file mode 100644 index 00000000..75c43e8e --- /dev/null +++ b/firmware/apps/trace/Makefile @@ -0,0 +1,3 @@ +C_FILES += $(C_LIBUSB_RT) + +C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c index e69de29b..aabaa41b 100644 --- a/firmware/apps/trace/main.c +++ b/firmware/apps/trace/main.c @@ -0,0 +1,209 @@ +// FIXME: Copyright license here +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "board.h" +#include "simtrace.h" +#include "utils.h" +#include "osmocom/core/timer.h" + +unsigned int g_unique_id[4]; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ +typedef struct { + /* static initialization, called whether or not the usb config is active */ + void (*configure) (void); + /* initialization function after the config was selected */ + void (*init) (void); + /* de-initialization before selecting new config */ + void (*exit) (void); + /* main loop content for given configuration */ + void (*run) (void); + /* Interrupt handler for USART1 */ + void (*usart0_irq) (void); + /* Interrupt handler for USART1 */ + void (*usart1_irq) (void); +} conf_func; + +static const conf_func config_func_ptrs[] = { + /* array slot 0 is empty, usb configs start at 1 */ +#ifdef HAVE_SNIFFER + [CFG_NUM_SNIFF] = { + .configure = Sniffer_configure, + .init = Sniffer_init, + .exit = Sniffer_exit, + .run = Sniffer_run, + }, +#endif +#ifdef HAVE_CCID + [CFG_NUM_CCID] = { + .configure = CCID_configure, + .init = CCID_init, + .exit = CCID_exit, + .run = CCID_run, + }, +#endif +#ifdef HAVE_CARDEM + [CFG_NUM_PHONE] = { + .configure = mode_cardemu_configure, + .init = mode_cardemu_init, + .exit = mode_cardemu_exit, + .run = mode_cardemu_run, + .usart0_irq = mode_cardemu_usart0_irq, + .usart1_irq = mode_cardemu_usart1_irq, + }, +#endif +#ifdef HAVE_MITM + [CFG_NUM_MITM] = { + .configure = MITM_configure, + .init = MITM_init, + .exit = MITM_exit, + .run = MITM_run, + }, +#endif +}; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ +#if defined(HAVE_SNIFFER) +static volatile enum confNum simtrace_config = CFG_NUM_SNIFF; +#elif defined(HAVE_CARDEM) +static volatile enum confNum simtrace_config = CFG_NUM_PHONE; +#elif defined(HAVE_CCID) +static volatile enum confNum simtrace_config = CFG_NUM_CCID; +#endif + +/*---------------------------------------------------------------------------- + * Callbacks + *----------------------------------------------------------------------------*/ + +void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) +{ + TRACE_INFO_WP("cfgChanged%d ", cfgnum); + simtrace_config = cfgnum; +} + +void USART1_IrqHandler(void) +{ + if (config_func_ptrs[simtrace_config].usart1_irq) + config_func_ptrs[simtrace_config].usart1_irq(); +} + +void USART0_IrqHandler(void) +{ + if (config_func_ptrs[simtrace_config].usart0_irq) + config_func_ptrs[simtrace_config].usart0_irq(); +} + +/* returns '1' in case we should break any endless loop */ +static void check_exec_dbg_cmd(void) +{ + int ch; + + if (!UART_IsRxReady()) + return; + + ch = UART_GetChar(); + + board_exec_dbg_cmd(ch); +} + +/*------------------------------------------------------------------------------ + * Main + *------------------------------------------------------------------------------*/ +#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second +extern int main(void) +{ + uint8_t isUsbConnected = 0; + enum confNum last_simtrace_config = simtrace_config; + unsigned int i = 0; + + led_init(); + led_blink(LED_RED, BLINK_3O_5F); + + /* Enable watchdog for 500ms, with no window */ + WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | + (WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500)); + + PIO_InitializeInterrupts(0); + + EEFC_ReadUniqueID(g_unique_id); + + printf("\n\r\n\r" + "=============================================================================\n\r" + "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r" + "=============================================================================\n\r"); + + TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID); + TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r", + g_unique_id[0], g_unique_id[1], + g_unique_id[2], g_unique_id[3]); + TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos); + + board_main_top(); + + TRACE_INFO("USB init...\n\r"); + SIMtrace_USB_Initialize(); + + while (USBD_GetState() < USBD_STATE_CONFIGURED) { + WDT_Restart(WDT); + check_exec_dbg_cmd(); +#if 0 + if (i >= MAX_USB_ITER * 3) { + TRACE_ERROR("Resetting board (USB could " + "not be configured)\n\r"); + USBD_Disconnect(); + NVIC_SystemReset(); + } +#endif + i++; + } + + TRACE_INFO("calling configure of all configurations...\n\r"); + for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); + ++i) { + if (config_func_ptrs[i].configure) + config_func_ptrs[i].configure(); + } + + TRACE_INFO("calling init of config %u...\n\r", simtrace_config); + config_func_ptrs[simtrace_config].init(); + last_simtrace_config = simtrace_config; + + TRACE_INFO("entering main loop...\n\r"); + while (1) { + WDT_Restart(WDT); +#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG + const char rotor[] = { '-', '\\', '|', '/' }; + putchar('\b'); + putchar(rotor[i++ % ARRAY_SIZE(rotor)]); +#endif + check_exec_dbg_cmd(); + osmo_timers_prepare(); + osmo_timers_update(); + + if (USBD_GetState() < USBD_STATE_CONFIGURED) { + + if (isUsbConnected) { + isUsbConnected = 0; + } + } else if (isUsbConnected == 0) { + TRACE_INFO("USB is now configured\n\r"); + + isUsbConnected = 1; + } + if (last_simtrace_config != simtrace_config) { + TRACE_INFO("USB config chg %u -> %u\n\r", + last_simtrace_config, simtrace_config); + config_func_ptrs[last_simtrace_config].exit(); + config_func_ptrs[simtrace_config].init(); + last_simtrace_config = simtrace_config; + } else { + config_func_ptrs[simtrace_config].run(); + } + } +} diff --git a/firmware/apps/trace/usb_strings.txt b/firmware/apps/trace/usb_strings.txt new file mode 100644 index 00000000..0e797ac2 --- /dev/null +++ b/firmware/apps/trace/usb_strings.txt @@ -0,0 +1,10 @@ +sysmocom - s.f.m.c. GmbH +SIMtrace 2 compatible device +SIMtrace Sniffer +SIMtrace CCID +SIMtrace Phone +SIMtrace MITM +CardEmulator Modem 1 +CardEmulator Modem 2 +CardEmulator Modem 3 +CardEmulator Modem 4 From 38a467e630bbd04db427df67f25c958f027fdc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 4 Jun 2018 16:30:01 +0200 Subject: [PATCH 07/30] enable (empty) sniffer support for SIMtrace board --- firmware/libboard/simtrace/include/board.h | 4 ++-- firmware/libcommon/source/sniffer.c | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index 742ce7c3..3b8296be 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -11,7 +11,7 @@ /** Phone (SIM card emulator)/CCID Reader/MITM configuration **/ /* Normally the communication lines between phone and SIM card are disconnected */ // Disconnect SIM card I/O, VPP line from the phone lines -// FIXME: Per default pins are input, therefore high-impedance, therefore they don not activate the bus switch, right? +// FIXME: Per default pins are input, therefore high-impedance, therefore the bus switch is in an unknown state by default for hardware version <= 1.4. It should be pulled high by an external resistor to set the bus switch to high-impedance (e.g. off). #define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} // Disconnect SIM card RST, CLK line from the phone lines #define PIN_IO_SW_DEFAULT {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} @@ -82,7 +82,7 @@ #define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU #define BOARD_USB_RELEASE 0x000 -//#define HAVE_SNIFFER +#define HAVE_SNIFFER #define HAVE_CCID #define HAVE_CARDEM //#define HAVE_MITM diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c index 67c11a22..06edb224 100644 --- a/firmware/libcommon/source/sniffer.c +++ b/firmware/libcommon/source/sniffer.c @@ -27,14 +27,15 @@ * ---------------------------------------------------------------------------- */ +#include "board.h" +#include "simtrace.h" + #ifdef HAVE_SNIFFER /*------------------------------------------------------------------------------ * Headers *------------------------------------------------------------------------------*/ -#include "board.h" - #include /*------------------------------------------------------------------------------ @@ -67,6 +68,12 @@ static struct Usart_info usart_info = { .state = USART_RCV, }; + +int check_data_from_phone(void) +{ + TRACE_INFO("check data from phone\n\r"); +} + /*----------------------------------------------------------------------------- * Initialization routine *-----------------------------------------------------------------------------*/ @@ -74,22 +81,22 @@ static struct Usart_info usart_info = { /* Called during USB enumeration after device is enumerated by host */ void Sniffer_configure(void) { - TRACE_INFO("Sniffer config\n"); + TRACE_INFO("Sniffer config\n\r"); } /* called when *different* configuration is set by host */ void Sniffer_exit(void) { - TRACE_INFO("Sniffer exit\n"); + TRACE_INFO("Sniffer exit\n\r"); USART_DisableIt(USART_PHONE, US_IER_RXRDY); NVIC_DisableIRQ(USART1_IRQn); USART_SetReceiverEnabled(USART_PHONE, 0); } -/* called when *CCID* configuration is set by host */ +/* called when *Sniffer* configuration is set by host */ void Sniffer_init(void) { - TRACE_INFO("Sniffer Init\n"); + TRACE_INFO("Sniffer Init\n\r"); /* Configure ISO7816 driver */ PIO_Configure(pinsISO7816_sniff, PIO_LISTSIZE(pinsISO7816_sniff)); PIO_Configure(pins_bus, PIO_LISTSIZE(pins_bus)); From b53ab5b4ef44add1ccaa28a3568c7e8825ba0a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 4 Jun 2018 16:30:48 +0200 Subject: [PATCH 08/30] add more USB configuration checks and error messages --- firmware/apps/trace/main.c | 72 +++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c index aabaa41b..54b42429 100644 --- a/firmware/apps/trace/main.c +++ b/firmware/apps/trace/main.c @@ -1,4 +1,22 @@ -// FIXME: Copyright license here +/* + * (C) 2010-2017 by Harald Welte + * (C) 2018 by Kevin Redon + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ /*------------------------------------------------------------------------------ * Headers *------------------------------------------------------------------------------*/ @@ -84,6 +102,9 @@ static volatile enum confNum simtrace_config = CFG_NUM_CCID; void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) { TRACE_INFO_WP("cfgChanged%d ", cfgnum); + if (cfgnum >= sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) { + TRACE_FATAL_WP("no functions defined for configuration %d\n\r", cfgnum); + } simtrace_config = cfgnum; } @@ -144,10 +165,13 @@ extern int main(void) g_unique_id[2], g_unique_id[3]); TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos); + TRACE_INFO("cfg %d\n\r", simtrace_config); + board_main_top(); TRACE_INFO("USB init...\n\r"); SIMtrace_USB_Initialize(); + TRACE_INFO_WP("USBD_Inited\n\r"); while (USBD_GetState() < USBD_STATE_CONFIGURED) { WDT_Restart(WDT); @@ -164,14 +188,26 @@ extern int main(void) } TRACE_INFO("calling configure of all configurations...\n\r"); - for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); - ++i) { - if (config_func_ptrs[i].configure) + for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); ++i) { + if (config_func_ptrs[i].configure) { config_func_ptrs[i].configure(); + } else { + TRACE_WARNING("no configure function defined for configuration %d\n\r", i); + } } + TRACE_INFO("cfg %d\n\r", simtrace_config); + TRACE_INFO("calling init of config %u...\n\r", simtrace_config); - config_func_ptrs[simtrace_config].init(); + if (simtrace_config >= sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) { + TRACE_ERROR("no functions defined for configuration %d\n\r", simtrace_config); + } else { + if (config_func_ptrs[simtrace_config].init) { + config_func_ptrs[simtrace_config].init(); + } else { + TRACE_ERROR("no init function defined for configuration %d\n\r", simtrace_config); + } + } last_simtrace_config = simtrace_config; TRACE_INFO("entering main loop...\n\r"); @@ -199,11 +235,31 @@ extern int main(void) if (last_simtrace_config != simtrace_config) { TRACE_INFO("USB config chg %u -> %u\n\r", last_simtrace_config, simtrace_config); - config_func_ptrs[last_simtrace_config].exit(); - config_func_ptrs[simtrace_config].init(); + if (last_simtrace_config < sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) { + if (config_func_ptrs[last_simtrace_config].exit) { + config_func_ptrs[last_simtrace_config].exit(); + } else { + TRACE_WARNING("exit not defined for configuration %d\n\r", last_simtrace_config); + } + } else { + TRACE_ERROR("no functions defined for configuration %d\n\r", last_simtrace_config); + } + if (simtrace_config < sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) { + if (config_func_ptrs[simtrace_config].init) { + config_func_ptrs[simtrace_config].init(); + } else { + TRACE_WARNING("init not defined for configuration %d\n\r", simtrace_config); + } + } else { + TRACE_FATAL("no functions defined for configuration %d\n\r", simtrace_config); + } last_simtrace_config = simtrace_config; } else { - config_func_ptrs[simtrace_config].run(); + if (config_func_ptrs[simtrace_config].run) { + config_func_ptrs[simtrace_config].run(); + } else { + TRACE_ERROR("run not defined for configuration %d\n\r", simtrace_config); + } } } } From a1f198276d5600eefb5ec63bf2ad145861527aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Wed, 6 Jun 2018 16:13:48 +0200 Subject: [PATCH 09/30] sniff mode: handle USART 1 RX interrupt to show sniffer data --- firmware/apps/trace/main.c | 1 + firmware/libcommon/include/simtrace.h | 2 ++ firmware/libcommon/source/sniffer.c | 35 +++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c index 54b42429..60963620 100644 --- a/firmware/apps/trace/main.c +++ b/firmware/apps/trace/main.c @@ -54,6 +54,7 @@ static const conf_func config_func_ptrs[] = { .init = Sniffer_init, .exit = Sniffer_exit, .run = Sniffer_run, + .usart1_irq = Sniffer_usart1_irq, }, #endif #ifdef HAVE_CCID diff --git a/firmware/libcommon/include/simtrace.h b/firmware/libcommon/include/simtrace.h index 348cc57f..21921cab 100644 --- a/firmware/libcommon/include/simtrace.h +++ b/firmware/libcommon/include/simtrace.h @@ -108,6 +108,8 @@ extern void CCID_run( void ); extern void mode_cardemu_run(void); extern void MITM_run( void ); +/* IRQ functions */ +extern void Sniffer_usart1_irq(void); extern void mode_cardemu_usart0_irq(void); extern void mode_cardemu_usart1_irq(void); diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c index 06edb224..fa272eb1 100644 --- a/firmware/libcommon/source/sniffer.c +++ b/firmware/libcommon/source/sniffer.c @@ -58,7 +58,7 @@ static const Pin pPwr[] = { /* Enable power converter 4.5-6V to 3.3V; low: off */ {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}, - /* Enable second power converter: VCC_PHONE to VCC_SIM; high: on */ + /* Enable power forwarding: VCC_PHONE to VCC_SIM; high: on */ {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} }; @@ -68,10 +68,37 @@ static struct Usart_info usart_info = { .state = USART_RCV, }; +/* Ring buffer to store sniffer communication data */ +static struct ringbuf sniff_buffer; + +/*------------------------------------------------------------------------------ + * Global functions + *------------------------------------------------------------------------------*/ + +void Sniffer_usart1_irq(void) +{ + /* Read channel status register */ + uint32_t csr = usart_info.base->US_CSR & usart_info.base->US_IMR; + /* Verify if character has been received */ + if (csr & US_CSR_RXRDY) { + /* Read communication data byte between phone and SIM */ + uint8_t byte = usart_info.base->US_RHR; + /* Store sniffed data into buffer (also clear interrupt */ + rbuf_write(&sniff_buffer, byte); + } +} + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ int check_data_from_phone(void) { - TRACE_INFO("check data from phone\n\r"); + /* Display sniffed data */ + while (!rbuf_is_empty(&sniff_buffer)) { + uint8_t byte = rbuf_read(&sniff_buffer); + TRACE_INFO_WP("0x%02x ", byte); + } } /*----------------------------------------------------------------------------- @@ -97,6 +124,10 @@ void Sniffer_exit(void) void Sniffer_init(void) { TRACE_INFO("Sniffer Init\n\r"); + + /* Clear ring buffer containing the sniffed data */ + rbuf_reset(&sniff_buffer); + /* Configure ISO7816 driver */ PIO_Configure(pinsISO7816_sniff, PIO_LISTSIZE(pinsISO7816_sniff)); PIO_Configure(pins_bus, PIO_LISTSIZE(pins_bus)); From 86ea4faef68a976de41fb9a4c06bae9d187746b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Wed, 6 Jun 2018 17:02:33 +0200 Subject: [PATCH 10/30] SIMtrace board: comment and fix pin definition --- firmware/libboard/simtrace/include/board.h | 156 ++++++++++++--------- 1 file changed, 90 insertions(+), 66 deletions(-) diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index 3b8296be..46483137 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -1,88 +1,112 @@ #pragma once #include "board_common.h" -/** Name of the board */ +/* Name of the board */ #define BOARD_NAME "SAM3S-SIMTRACE" -/** Board definition */ +/* Board definition */ #define simtrace +/* Board main oscillator frequency (in Hz) */ #define BOARD_MAINOSC 18432000 -/** Phone (SIM card emulator)/CCID Reader/MITM configuration **/ -/* Normally the communication lines between phone and SIM card are disconnected */ -// Disconnect SIM card I/O, VPP line from the phone lines -// FIXME: Per default pins are input, therefore high-impedance, therefore the bus switch is in an unknown state by default for hardware version <= 1.4. It should be pulled high by an external resistor to set the bus switch to high-impedance (e.g. off). -#define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} -// Disconnect SIM card RST, CLK line from the phone lines -#define PIN_IO_SW_DEFAULT {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} -#define PINS_BUS_DEFAULT PIN_SC_SW_DEFAULT, PIN_IO_SW_DEFAULT +/** Pin configuration **/ +/* Button to force bootloader start (shorted to ground when pressed */ +#define PIN_BOOTLOADER_SW {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP} +/* Enable powering the card using the second 3.3 V output of the LDO (active high) */ +#define SIM_PWEN_PIN {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} +/* Card presence pin */ +#define SW_SIM PIO_PA8 +/* Pull card presence pin high (shorted to ground in card slot when card is present) */ +#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE } + +/** Smart card connection **/ +/* Card RST reset signal input (active low; RST_SIM in schematic) */ +#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +/* Card I/O data signal input/output (I/O_SIM in schematic) */ +#define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* Card CLK clock input (CLK_SIM in schematic) */ +#define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} +/* ISO7816-communication related pins */ +#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2 +/* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */ +#define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} +/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */ +#define PIN_SIM_CLK_INPUT {PIO_PA4B_TCLK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} +/* Pins used to measure ETU timing (using timer counter) */ +#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT + +/** Phone connection **/ +/* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */ +#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} +/* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */ +#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH } +/* Phone I/O data signal input/output (I/O_PHONE in schematic) */ +#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* Phone CLK clock input (CLK_PHONE in schematic) */ +#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* Pin used for phone USIM slot 1 communication */ +#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST +/* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */ +#define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */ +#define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} + +/** Default configuration **/ +/* Disconnect VPP, CLK, and RST lines between card and phone using bus switch (high sets bus switch to high-impedance) */ +#define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} +/* Disconnect I/O line between card and phone using bus switch (high sets bus switch to high-impedance) */ +#define PIN_IO_SW_DEFAULT {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} +/* Disconnect all lines (VPP, CLK, RST, and I/O) between card and phone */ +#define PINS_BUS_DEFAULT PIN_SC_SW_DEFAULT, PIN_IO_SW_DEFAULT /** Sniffer configuration **/ -// Connect VPP, CLK and RST lines from smartcard to the phone +/* Connect VPP, CLK, and RST lines between card and phone using bus switch (low connects signals on bus switch) */ #define PIN_SC_SW_SNIFF {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +/* Connect I/O line between card and phone using bus switch (low connects signals on bus switch) */ #define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +/* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */ #define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF - +/* Pins used to sniff phone-card communication */ #define PINS_SIM_SNIFF_SIM PIN_PHONE_IO, PIN_PHONE_CLK +/* Disable power converter 4.5-6V to 3.3V; (active high) */ +#define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +/* Enable power switch: VCC_PHONE to VCC_SIM; (active high) */ +#define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} +/* Use phone VCC to power card */ +#define PWR_PINS PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF -#define SIM_PWEN_PIN {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} - -#define PWR_PINS \ - /* Enable power converter 4.5-6V to 3.3V; low: off */ \ - {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}, \ - /* Enable second power converter: VCC_PHONE to VCC_SIM; high: on */ \ - {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} - -#define SW_SIM PIO_PA8 -#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE } -//#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_IT_EDGE} - -/// PIN used for resetting the smartcard -// FIXME: Card is resetted with pin set to 0 --> PIO_OUTPUT_1 as default is right? -#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} - -/// Pins used for connect the smartcard -#define PIN_SIM_IO_INPUT {PIO_PA1, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} -#define PIN_SIM_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} -#define PIN_SIM_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} -#define PIN_SIM_CLK_INPUT {PIO_PA4, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} -//#define PINS_ISO7816 PIN_USART1_TXD, PIN_USART1_SCK, PIN_ISO7816_RSTMC -#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2 - -#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT - -#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} -#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH } -#define PIN_PHONE_IO_INPUT {PIO_PA21, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} -#define PIN_PHONE_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} -#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} // External Clock Input on PA28 -//#define PIN_PHONE_CLK {PIO_PA23A_SCK1, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} // External Clock Input on PA28 -#define PIN_PHONE_CLK_INPUT {PIO_PA29, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} -#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST -//, VCC_PHONE - -#define PIN_BOOTLOADER_SW {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP} - -//** SPI interface **/ -/// SPI MISO pin definition (PA12). -#define PIN_SPI_MISO {1 << 12, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP} -/// SPI MOSI pin definition (PA13). -#define PIN_SPI_MOSI {1 << 13, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT} -/// SPI SPCK pin definition (PA14). -#define PIN_SPI_SPCK {1 << 14, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT} -/// SPI pins definition. Contains MISO, MOSI & SPCK (PA12, PA13 & PA14). -#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SPCK -/// SPI chip select 0 pin definition (PA11). -#define PIN_SPI_NPCS0 {1 << 11, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/** External SPI flash interface **/ +/* SPI MISO pin definition */ +#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP} +/* SPI MOSI pin definition */ +#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* SPI SCK pin definition */ +#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* SPI pins definition. Contains MISO, MOSI & SCK */ +#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SCK +/* SPI chip select 0 pin definition */ +#define PIN_SPI_NPCS0 {PIO_PA11A_NPCS0, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT} +/* SPI flash write protect pin (active low, pulled low) */ +#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +/** USB definitions */ +/* OpenMoko SIMtrace 2 USB vendor ID */ +#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO +/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */ +#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2 +/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */ +#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU +/* USB release number (bcdDevice, shown as 0.00) */ +#define BOARD_USB_RELEASE 0x000 +/* Indicate SIMtrace is bus power in USB attributes */ #define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP -#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO -#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2 -#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU -#define BOARD_USB_RELEASE 0x000 - +/** Supported modes */ +/* SIMtrace board supports sniffer mode */ #define HAVE_SNIFFER +/* SIMtrace board supports CCID mode */ #define HAVE_CCID +/* SIMtrace board supports card emulation mode */ #define HAVE_CARDEM +/* SIMtrace board supports man-in-the-middle mode */ //#define HAVE_MITM From 7f4f8983dd9cbb734fb30c6af70baab5daa75880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Wed, 6 Jun 2018 17:03:15 +0200 Subject: [PATCH 11/30] USBD: send empty packet when non-existing descriptor string is requested Sometimes descriptor string 0xee is requested. This is a mechanism used by Microsoft Windows to further identify the USB device. Instead of stalling, as is the original code, leading to an USB reset, we send an empty packet. I am not sure if sending an empty string would be better, but an empty packet seems sufficient. --- .../usb/device/core/USBDDriver.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c b/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c index 058f5634..22889cf2 100644 --- a/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c +++ b/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c @@ -2,6 +2,7 @@ * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2008, Atmel Corporation + * Copyright (c) 2018, Kevin Redon * * All rights reserved. * @@ -331,8 +332,13 @@ static void GetDescriptor( /* Check if descriptor exists */ if (indexRDesc >= numStrings) { - - USBD_Stall(0); + /* Sometimes descriptor string 0xee is requested. + * This is a mechanism used by Microsoft Windows to further identify the USB device. + * Instead of stalling, as is the original code, leading to an USB reset, we send an empty packet. + * I am not sure if sending an empty string would be better, but an empty packet seems sufficient. + */ + //USBD_Stall(0); + USBD_Write(0, NULL, 0, 0, 0); } else { From d0b4a9da81785ff40716daa98abb4e7d617dd31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Thu, 7 Jun 2018 18:56:41 +0200 Subject: [PATCH 12/30] sniff: use USART 0 instead of USART 1 Use USART 0 connected to the SIM card side to sniff the communication. The card side can also measure ETU times. Do proper pin initialization. This code can already capture the ATR communication between phone and card. --- firmware/apps/trace/main.c | 5 +- firmware/libboard/simtrace/include/board.h | 18 ++-- firmware/libcommon/include/simtrace.h | 3 +- firmware/libcommon/source/sniffer.c | 109 ++++++++++----------- 4 files changed, 65 insertions(+), 70 deletions(-) diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c index 60963620..bc7c0302 100644 --- a/firmware/apps/trace/main.c +++ b/firmware/apps/trace/main.c @@ -54,7 +54,7 @@ static const conf_func config_func_ptrs[] = { .init = Sniffer_init, .exit = Sniffer_exit, .run = Sniffer_run, - .usart1_irq = Sniffer_usart1_irq, + .usart0_irq = Sniffer_usart0_irq, }, #endif #ifdef HAVE_CCID @@ -165,8 +165,7 @@ extern int main(void) g_unique_id[0], g_unique_id[1], g_unique_id[2], g_unique_id[3]); TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos); - - TRACE_INFO("cfg %d\n\r", simtrace_config); + TRACE_INFO("USB configuration used: %d\n\r", simtrace_config); board_main_top(); diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index 46483137..00d32ee9 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -21,13 +21,11 @@ /** Smart card connection **/ /* Card RST reset signal input (active low; RST_SIM in schematic) */ -#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +#define PIN_SIM_RST {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} /* Card I/O data signal input/output (I/O_SIM in schematic) */ #define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} /* Card CLK clock input (CLK_SIM in schematic) */ #define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} -/* ISO7816-communication related pins */ -#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2 /* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */ #define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} /* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */ @@ -66,15 +64,23 @@ #define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} /* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */ #define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF +/* Use RST_SIM line to detect phone issued card reset */ +#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE } /* Pins used to sniff phone-card communication */ -#define PINS_SIM_SNIFF_SIM PIN_PHONE_IO, PIN_PHONE_CLK -/* Disable power converter 4.5-6V to 3.3V; (active high) */ +#define PINS_SIM_SNIFF_SIM PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF +/* Disable power converter 4.5-6V to 3.3V (active high) */ #define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} -/* Enable power switch: VCC_PHONE to VCC_SIM; (active high) */ +/* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */ #define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} /* Use phone VCC to power card */ #define PWR_PINS PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF +/** CCID configuration */ +/* Card RST reset signal input (active low; RST_SIM in schematic) */ +#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} +/* ISO7816-communication related pins */ +#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2 + /** External SPI flash interface **/ /* SPI MISO pin definition */ #define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP} diff --git a/firmware/libcommon/include/simtrace.h b/firmware/libcommon/include/simtrace.h index 21921cab..e39d1dc1 100644 --- a/firmware/libcommon/include/simtrace.h +++ b/firmware/libcommon/include/simtrace.h @@ -77,7 +77,6 @@ typedef struct { extern const USBConfigurationDescriptor *configurationDescriptorsArr[]; -int check_data_from_phone(); void update_fidi(uint8_t fidi); void ISR_PhoneRST( const Pin *pPin); @@ -109,7 +108,7 @@ extern void mode_cardemu_run(void); extern void MITM_run( void ); /* IRQ functions */ -extern void Sniffer_usart1_irq(void); +extern void Sniffer_usart0_irq(void); extern void mode_cardemu_usart0_irq(void); extern void mode_cardemu_usart1_irq(void); diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c index fa272eb1..7cc688b3 100644 --- a/firmware/libcommon/source/sniffer.c +++ b/firmware/libcommon/source/sniffer.c @@ -1,32 +1,22 @@ -/* ---------------------------------------------------------------------------- - * ATMEL Microcontroller Software Support - * ---------------------------------------------------------------------------- - * Copyright (c) 2009, Atmel Corporation +/* + * (C) 2010-2017 by Harald Welte + * (C) 2018 by Kevin Redon + * All Rights Reserved * - * All rights reserved. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * 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 Affero General Public License for more details. * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the disclaimer below. + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . * - * Atmel's name may not be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * ---------------------------------------------------------------------------- */ - #include "board.h" #include "simtrace.h" @@ -47,27 +37,24 @@ /** Maximum ATR ucSize in bytes.*/ #define MAX_ATR_SIZE 55 + /*------------------------------------------------------------------------------ * Internal variables *------------------------------------------------------------------------------*/ -/** ISO7816 pins */ -static const Pin pinsISO7816_sniff[] = { PINS_SIM_SNIFF_SIM }; +/* Pin configuration to sniff communication (using USART connection to SIM card) */ +static const Pin pins_sniff[] = { PINS_SIM_SNIFF_SIM }; +/* Connect phone to card using bus switch */ static const Pin pins_bus[] = { PINS_BUS_SNIFF }; - -static const Pin pPwr[] = { - /* Enable power converter 4.5-6V to 3.3V; low: off */ - {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}, - - /* Enable power forwarding: VCC_PHONE to VCC_SIM; high: on */ - {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} -}; - -static struct Usart_info usart_info = { - .base = USART_PHONE, - .id = ID_USART_PHONE, +/* Power card using phone VCC */ +static const Pin pins_power[] = { PWR_PINS }; +/* Timer Counter pins to measure ETU timing */ +static const Pin pins_tc[] = { PINS_TC }; +/* USART peripheral used to sniff communication */ +static struct Usart_info sniff_usart = { + .base = USART_SIM, + .id = ID_USART_SIM, .state = USART_RCV, }; - /* Ring buffer to store sniffer communication data */ static struct ringbuf sniff_buffer; @@ -75,14 +62,14 @@ static struct ringbuf sniff_buffer; * Global functions *------------------------------------------------------------------------------*/ -void Sniffer_usart1_irq(void) +void Sniffer_usart0_irq(void) { /* Read channel status register */ - uint32_t csr = usart_info.base->US_CSR & usart_info.base->US_IMR; + uint32_t csr = sniff_usart.base->US_CSR & sniff_usart.base->US_IMR; /* Verify if character has been received */ if (csr & US_CSR_RXRDY) { /* Read communication data byte between phone and SIM */ - uint8_t byte = usart_info.base->US_RHR; + uint8_t byte = sniff_usart.base->US_RHR; /* Store sniffed data into buffer (also clear interrupt */ rbuf_write(&sniff_buffer, byte); } @@ -92,7 +79,7 @@ void Sniffer_usart1_irq(void) * Internal functions *------------------------------------------------------------------------------*/ -int check_data_from_phone(void) +static void check_sniffed_data(void) { /* Display sniffed data */ while (!rbuf_is_empty(&sniff_buffer)) { @@ -115,9 +102,10 @@ void Sniffer_configure(void) void Sniffer_exit(void) { TRACE_INFO("Sniffer exit\n\r"); - USART_DisableIt(USART_PHONE, US_IER_RXRDY); - NVIC_DisableIRQ(USART1_IRQn); - USART_SetReceiverEnabled(USART_PHONE, 0); + USART_DisableIt(sniff_usart.base, US_IER_RXRDY); + /* NOTE: don't forget to set the IRQ according to the USART peripheral used */ + NVIC_DisableIRQ(USART0_IRQn); + USART_SetReceiverEnabled(sniff_usart.base, 0); } /* called when *Sniffer* configuration is set by host */ @@ -125,25 +113,28 @@ void Sniffer_init(void) { TRACE_INFO("Sniffer Init\n\r"); + /* Configure pins to sniff communication between phone and card */ + PIO_Configure(pins_sniff, PIO_LISTSIZE(pins_sniff)); + /* Configure pins to connect phone to card */ + PIO_Configure(pins_bus, PIO_LISTSIZE(pins_bus)); + /* Configure pins to forward phone power to card */ + PIO_Configure(pins_power, PIO_LISTSIZE(pins_power)); + /* Clear ring buffer containing the sniffed data */ rbuf_reset(&sniff_buffer); - - /* Configure ISO7816 driver */ - PIO_Configure(pinsISO7816_sniff, PIO_LISTSIZE(pinsISO7816_sniff)); - PIO_Configure(pins_bus, PIO_LISTSIZE(pins_bus)); - - PIO_Configure(pPwr, PIO_LISTSIZE(pPwr)); - - ISO7816_Init(&usart_info, CLK_SLAVE); - - USART_SetReceiverEnabled(USART_PHONE, 1); - USART_EnableIt(USART_PHONE, US_IER_RXRDY); - NVIC_EnableIRQ(USART1_IRQn); + /* Configure USART to as ISO-7816 slave communication to sniff communication */ + ISO7816_Init(&sniff_usart, CLK_SLAVE); + /* Only receive data when sniffing */ + USART_SetReceiverEnabled(sniff_usart.base, 1); + /* Enable interrupt to indicate when data has been received */ + USART_EnableIt(sniff_usart.base, US_IER_RXRDY); + /* Enable interrupt requests for the USART peripheral (warning: use IRQ corresponding to USART) */ + NVIC_EnableIRQ(USART0_IRQn); } /* main (idle/busy) loop of this USB configuration */ void Sniffer_run(void) { - check_data_from_phone(); + check_sniffed_data(); } #endif /* HAVE_SNIFFER */ From 2d972f59102a8ecd90a20cb0a8eb54793a32ec7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 11 Jun 2018 13:42:23 +0200 Subject: [PATCH 13/30] simtrace: add dedicated power pins configuration for sniffing --- firmware/libboard/simtrace/include/board.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index 00d32ee9..8e832ddb 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -14,6 +14,8 @@ #define PIN_BOOTLOADER_SW {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP} /* Enable powering the card using the second 3.3 V output of the LDO (active high) */ #define SIM_PWEN_PIN {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} +/* Enable powering the SIM card */ +#define PWR_PINS SIM_PWEN_PIN /* Card presence pin */ #define SW_SIM PIO_PA8 /* Pull card presence pin high (shorted to ground in card slot when card is present) */ @@ -49,7 +51,7 @@ /* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */ #define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} -/** Default configuration **/ +/** Default pin configuration **/ /* Disconnect VPP, CLK, and RST lines between card and phone using bus switch (high sets bus switch to high-impedance) */ #define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} /* Disconnect I/O line between card and phone using bus switch (high sets bus switch to high-impedance) */ @@ -64,16 +66,14 @@ #define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} /* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */ #define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF -/* Use RST_SIM line to detect phone issued card reset */ -#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE } /* Pins used to sniff phone-card communication */ -#define PINS_SIM_SNIFF_SIM PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF +#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST /* Disable power converter 4.5-6V to 3.3V (active high) */ #define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} /* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */ #define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} /* Use phone VCC to power card */ -#define PWR_PINS PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF +#define PINS_PWR_SNIFF PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF /** CCID configuration */ /* Card RST reset signal input (active low; RST_SIM in schematic) */ From 762276e271004a22e49153863d8780c45a0fdce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 11 Jun 2018 13:43:27 +0200 Subject: [PATCH 14/30] board: comment USART definitions and add corresponding IRQ numbers --- firmware/libboard/common/include/board_common.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/firmware/libboard/common/include/board_common.h b/firmware/libboard/common/include/board_common.h index 9cd1f89f..6260daec 100644 --- a/firmware/libboard/common/include/board_common.h +++ b/firmware/libboard/common/include/board_common.h @@ -77,10 +77,19 @@ #define BOARD_ISO7816_BASE_USART USART0 #define BOARD_ISO7816_ID_USART ID_USART0 +/* USART peripherals for a phone and SIM card setup */ +/* USART peripheral connected to the SIM card */ #define USART_SIM USART0 +/* ID of USART peripheral connected to the SIM card */ #define ID_USART_SIM ID_USART0 -#define USART_PHONE USART1 -#define ID_USART_PHONE ID_USART1 +/* Interrupt request ID of USART peripheral connected to the SIM card */ +#define IRQ_USART_SIM USART0_IRQn +/* USART peripheral connected to the phone */ +#define USART_PHONE USART1 +/* ID of USART peripheral connected to the phone */ +#define ID_USART_PHONE ID_USART1 +/* Interrupt request ID of USART peripheral connected to the phone */ +#define IRQ_USART_PHONE USART1_IRQn #define SIM_PWEN PIO_PA5 #define VCC_FWD PIO_PA26 From a34471d92361d2fa8f7155f9191cb897c9cb7802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 11 Jun 2018 13:45:16 +0200 Subject: [PATCH 15/30] simtrace: add support for sniffing on both USART --- firmware/apps/trace/main.c | 1 + firmware/libcommon/include/simtrace.h | 1 + 2 files changed, 2 insertions(+) diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c index bc7c0302..e705a17e 100644 --- a/firmware/apps/trace/main.c +++ b/firmware/apps/trace/main.c @@ -55,6 +55,7 @@ static const conf_func config_func_ptrs[] = { .exit = Sniffer_exit, .run = Sniffer_run, .usart0_irq = Sniffer_usart0_irq, + .usart1_irq = Sniffer_usart1_irq, }, #endif #ifdef HAVE_CCID diff --git a/firmware/libcommon/include/simtrace.h b/firmware/libcommon/include/simtrace.h index e39d1dc1..278d5d22 100644 --- a/firmware/libcommon/include/simtrace.h +++ b/firmware/libcommon/include/simtrace.h @@ -109,6 +109,7 @@ extern void MITM_run( void ); /* IRQ functions */ extern void Sniffer_usart0_irq(void); +extern void Sniffer_usart1_irq(void); extern void mode_cardemu_usart0_irq(void); extern void mode_cardemu_usart1_irq(void); From 2ab8f8e3fd67ecefda2e9cec190647bd514cc8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 11 Jun 2018 13:46:35 +0200 Subject: [PATCH 16/30] sniffer: add state definitions, improve IRQ handling, update pins configuration --- firmware/libcommon/source/sniffer.c | 105 +++++++++++++++++++++------- 1 file changed, 78 insertions(+), 27 deletions(-) diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c index 7cc688b3..987e3e51 100644 --- a/firmware/libcommon/source/sniffer.c +++ b/firmware/libcommon/source/sniffer.c @@ -17,6 +17,9 @@ * along with this program. If not, see . * */ +/* This code implement the Sniffer mode to sniff the communication between a SIM card and a phone. + * For historical reasons (i.e. SIMtrace hardware) the USART peripheral connected to the SIM card is used. + */ #include "board.h" #include "simtrace.h" @@ -35,20 +38,51 @@ /** Maximum ucSize in bytes of the smartcard answer to a command.*/ #define MAX_ANSWER_SIZE 10 -/** Maximum ATR ucSize in bytes.*/ -#define MAX_ATR_SIZE 55 +/*! Maximum Answer-To-Reset (ATR) size in bytes ucSize in bytes + * @note defined in ISO/IEC 7816-3:2006(E) section 8.2.1 as 32, on top the initial character TS of section 8.1 + * @remark technical there is no size limitation since Yi present in T0,TDi will indicate if more interface bytes are present, including TDi+i + */ +#define MAX_ATR_SIZE 33 + +/*! ISO 7816-3 states relevant to the sniff mode */ +enum iso7816_3_sniff_state { + ISO7816_S_RESET, /*!< in Reset */ + ISO7816_S_WAIT_ATR, /*!< waiting for ATR to start */ + ISO7816_S_IN_ATR, /*!< while we are receiving the ATR */ + ISO7816_S_WAIT_APDU, /*!< waiting for start of new APDU */ + ISO7816_S_IN_APDU, /*!< inside a single APDU */ + ISO7816_S_IN_PTS, /*!< while we are inside the PTS / PSS */ +}; + +/*! Answer-To-Reset (ATR) sub-states of ISO7816_S_IN_ATR + * @note defined in ISO/IEC 7816-3:2006(E) section 8 + */ +enum atr_sniff_state { + ATR_S_WAIT_TS, /*!< initial byte */ + ATR_S_WAIT_T0, /*!< format byte */ + ATR_S_WAIT_TA, /*!< first sub-group interface byte */ + ATR_S_WAIT_TB, /*!< second sub-group interface byte */ + ATR_S_WAIT_TC, /*!< third sub-group interface byte */ + ATR_S_WAIT_TD, /*!< fourth sub-group interface byte */ + ATR_S_WAIT_HIST, /*!< historical byte */ + ATR_S_WAIT_TCK, /*!< check byte */ + ATR_S_DONE, /*!< to indicated all ATR bytes have been received */ +}; /*------------------------------------------------------------------------------ * Internal variables *------------------------------------------------------------------------------*/ -/* Pin configuration to sniff communication (using USART connection to SIM card) */ -static const Pin pins_sniff[] = { PINS_SIM_SNIFF_SIM }; -/* Connect phone to card using bus switch */ + +/* note: the sniffer code is currently designed to support only one sniffing interface, but the hardware would support a second one. + * to support a second sniffer interface the code should be restructured to use handles. + */ +/* Pin configurations */ +/* Pin configuration to sniff communication (using USART connection card) */ +static const Pin pins_sniff[] = { PINS_SIM_SNIFF }; static const Pin pins_bus[] = { PINS_BUS_SNIFF }; -/* Power card using phone VCC */ -static const Pin pins_power[] = { PWR_PINS }; -/* Timer Counter pins to measure ETU timing */ +static const Pin pins_power[] = { PINS_PWR_SNIFF }; static const Pin pins_tc[] = { PINS_TC }; +/* USART related variables */ /* USART peripheral used to sniff communication */ static struct Usart_info sniff_usart = { .base = USART_SIM, @@ -58,23 +92,6 @@ static struct Usart_info sniff_usart = { /* Ring buffer to store sniffer communication data */ static struct ringbuf sniff_buffer; -/*------------------------------------------------------------------------------ - * Global functions - *------------------------------------------------------------------------------*/ - -void Sniffer_usart0_irq(void) -{ - /* Read channel status register */ - uint32_t csr = sniff_usart.base->US_CSR & sniff_usart.base->US_IMR; - /* Verify if character has been received */ - if (csr & US_CSR_RXRDY) { - /* Read communication data byte between phone and SIM */ - uint8_t byte = sniff_usart.base->US_RHR; - /* Store sniffed data into buffer (also clear interrupt */ - rbuf_write(&sniff_buffer, byte); - } -} - /*------------------------------------------------------------------------------ * Internal functions *------------------------------------------------------------------------------*/ @@ -88,6 +105,38 @@ static void check_sniffed_data(void) } } +/*! Interrupt Service Routine called on USART activity */ +void Sniffer_usart_irq(void) +{ + /* Read channel status register */ + uint32_t csr = sniff_usart.base->US_CSR & sniff_usart.base->US_IMR; + /* Verify if character has been received */ + if (csr & US_CSR_RXRDY) { + /* Read communication data byte between phone and SIM */ + uint8_t byte = sniff_usart.base->US_RHR; + /* Store sniffed data into buffer (also clear interrupt */ + rbuf_write(&sniff_buffer, byte); + } +} + +/*------------------------------------------------------------------------------ + * Global functions + *------------------------------------------------------------------------------*/ + +void Sniffer_usart1_irq(void) +{ + if (ID_USART1==sniff_usart.id) { + Sniffer_usart_irq(); + } +} + +void Sniffer_usart0_irq(void) +{ + if (ID_USART0==sniff_usart.id) { + Sniffer_usart_irq(); + } +} + /*----------------------------------------------------------------------------- * Initialization routine *-----------------------------------------------------------------------------*/ @@ -128,8 +177,10 @@ void Sniffer_init(void) USART_SetReceiverEnabled(sniff_usart.base, 1); /* Enable interrupt to indicate when data has been received */ USART_EnableIt(sniff_usart.base, US_IER_RXRDY); - /* Enable interrupt requests for the USART peripheral (warning: use IRQ corresponding to USART) */ - NVIC_EnableIRQ(USART0_IRQn); + /* Enable interrupt requests for the USART peripheral */ + NVIC_EnableIRQ(IRQ_USART_SIM); + + /* TODO configure RST pin ISR */ } /* main (idle/busy) loop of this USB configuration */ From 9a921ac63081e5de835c394805eb7707c948f42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 17 Jun 2018 22:31:21 +0200 Subject: [PATCH 17/30] USB: implement USB reset by setting the on-board pull-up on D+ low --- firmware/apps/dfu/main.c | 6 ++++++ firmware/libboard/common/include/board_common.h | 9 ++++----- firmware/libcommon/source/usb.c | 10 ++++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c index a90b9ac9..ff31296c 100644 --- a/firmware/apps/dfu/main.c +++ b/firmware/apps/dfu/main.c @@ -194,6 +194,12 @@ extern int main(void) board_main_top(); TRACE_INFO("USB init...\n\r"); + /* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */ + const Pin usb_dp_pullup = PIN_USB_PULLUP; + PIO_Configure(&usb_dp_pullup, 1); + PIO_Set(&usb_dp_pullup); + mdelay(15); + PIO_Clear(&usb_dp_pullup); USBDFU_Initialize(&dfu_descriptors); while (USBD_GetState() < USBD_STATE_CONFIGURED) { diff --git a/firmware/libboard/common/include/board_common.h b/firmware/libboard/common/include/board_common.h index 6260daec..f2314ced 100644 --- a/firmware/libboard/common/include/board_common.h +++ b/firmware/libboard/common/include/board_common.h @@ -94,11 +94,10 @@ #define SIM_PWEN PIO_PA5 #define VCC_FWD PIO_PA26 - -//** USB **/ -// USB pull-up control pin definition (PA16). -// Default: 1 (USB Pullup deactivated) -#define PIN_USB_PULLUP {1 << 16, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} +/** Pin configuration to control USB pull-up on D+ + * @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high + */ +#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} // Board has UDP controller #define BOARD_USB_UDP diff --git a/firmware/libcommon/source/usb.c b/firmware/libcommon/source/usb.c index bb77361b..d317435d 100644 --- a/firmware/libcommon/source/usb.c +++ b/firmware/libcommon/source/usb.c @@ -603,11 +603,17 @@ static const USBDDriverDescriptors driverDescriptors = { void SIMtrace_USB_Initialize(void) { + + /* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */ + const Pin usb_dp_pullup = PIN_USB_PULLUP; + PIO_Configure(&usb_dp_pullup, 1); + PIO_Set(&usb_dp_pullup); + mdelay(15); + PIO_Clear(&usb_dp_pullup); + // Get std USB driver USBDDriver *pUsbd = USBD_GetDriver(); - TRACE_DEBUG("."); - // Initialize standard USB driver USBDDriver_Initialize(pUsbd, &driverDescriptors, 0); // Multiple interface settings not supported USBD_Init(); From 88b2b077ef3e9b5fa764af3f7bd167c68592119c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 17 Jun 2018 22:33:29 +0200 Subject: [PATCH 18/30] DFU: unlock the flash before writing, verify written data, and relock it --- firmware/apps/dfu/main.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c index ff31296c..a5b6f74d 100644 --- a/firmware/apps/dfu/main.c +++ b/firmware/apps/dfu/main.c @@ -38,7 +38,7 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, switch (altif) { case ALTIF_RAM: addr = RAM_ADDR(offset); - if (addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) { + if (addr < IRAM_ADDR || addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) { g_dfu->state = DFU_STATE_dfuERROR; g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; @@ -47,13 +47,32 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, return DFU_RET_ZLP; case ALTIF_FLASH: addr = FLASH_ADDR(offset); - if (addr + len >= IFLASH_ADDR + IFLASH_SIZE) { + if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) { g_dfu->state = DFU_STATE_dfuERROR; g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; } + rc = FLASHD_Unlock(addr, addr + len, 0, 0); + if (rc != 0) { + TRACE_ERROR("DFU download flash unlock failed\n\r"); + /* FIXME: set error codes */ + return DFU_RET_STALL; + } rc = FLASHD_Write(addr, data, len); if (rc != 0) { + TRACE_ERROR("DFU download flash erase failed\n\r"); + /* FIXME: set error codes */ + return DFU_RET_STALL; + } + for (unsigned int i=0; i Date: Sun, 17 Jun 2018 22:34:47 +0200 Subject: [PATCH 19/30] DFU: uncomment print message when DFU is forced using the button --- firmware/libboard/simtrace/source/board_simtrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/libboard/simtrace/source/board_simtrace.c b/firmware/libboard/simtrace/source/board_simtrace.c index 5c865f01..e29161c0 100644 --- a/firmware/libboard/simtrace/source/board_simtrace.c +++ b/firmware/libboard/simtrace/source/board_simtrace.c @@ -44,7 +44,7 @@ int board_override_enter_dfu(void) /* Enter DFU bootloader in case the respective button is pressed */ if (PIO_Get(&bl_sw_pin) == 0) { - //printf("BOOTLOADER switch presssed -> Force DFU\n\r"); + printf("BOOTLOADER switch presssed -> Force DFU\n\r"); return 1; } else return 0; From 3f8a4c28e804909d1aa8eedebf4143009be3f07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 17 Jun 2018 22:35:17 +0200 Subject: [PATCH 20/30] DFU: only boot the application if it has a valid start --- .../libboard/common/source/board_cstartup_gnu.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/firmware/libboard/common/source/board_cstartup_gnu.c b/firmware/libboard/common/source/board_cstartup_gnu.c index f2d17aff..15c70ddd 100644 --- a/firmware/libboard/common/source/board_cstartup_gnu.c +++ b/firmware/libboard/common/source/board_cstartup_gnu.c @@ -159,9 +159,20 @@ void ResetException( void ) * not initialized yet */ g_dfu = &_g_dfu; if ((g_dfu->magic != USB_DFU_MAGIC) && !USBDFU_OverrideEnterDFU()) { - BootIntoApp(); - /* Infinite loop */ - while ( 1 ) ; + /* start application if valid + * the application starts with the vector table + * the first entry in the vector table is the initial stack pointer (SP) address + * the stack will be placed in RAM, which begins at 0x2000 0000 + * there is up to 48 KB of RAM (0xc000) + * since the stack grown "downwards" it should start at the end of the RAM: max 0x2000 c000 + * if the SP is not in this range (e.g. flash has been erased) there is no valid application + * the second entry in the vector table is the reset address, corresponding to the application start + */ + if (((*((uint32_t*)(IFLASH_ADDR+BOARD_DFU_BOOT_SIZE)))&0xFFFF0000)==0x20000000) { + BootIntoApp(); + /* Infinite loop */ + while ( 1 ) ; + } } #endif From 6b38297e20eb31d837024926033f0abc20ddea66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 17 Jun 2018 22:36:44 +0200 Subject: [PATCH 21/30] DFU: incread watchdog timeout and restart watchdog before writing in flash to prevent the watchdog to trigger while flashing --- firmware/apps/dfu/main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c index a5b6f74d..578f2f2f 100644 --- a/firmware/apps/dfu/main.c +++ b/firmware/apps/dfu/main.c @@ -10,6 +10,8 @@ #define ALTIF_FLASH 1 unsigned int g_unique_id[4]; +/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */ +static bool watchdog_configured = false; /*---------------------------------------------------------------------------- * Callbacks @@ -32,6 +34,10 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, int rc; /* address of the last allocated variable on the stack */ uint32_t stack_addr = (uint32_t)&rc; + /* kick the dog to have enough time to flash */ + if (watchdog_configured) { + WDT_Restart(WDT); + } printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len); @@ -186,9 +192,10 @@ extern int main(void) led_blink(LED_RED, BLINK_3O_30F); #endif - /* Enable watchdog for 500ms, with no window */ + /* Enable watchdog for 2000ms, with no window */ WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | - (WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500)); + (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000)); + watchdog_configured = true; PIO_InitializeInterrupts(0); From 78a8ab71e1bf6846712fe5689704a00cab3cf9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 24 Jun 2018 11:27:09 +0200 Subject: [PATCH 22/30] DFU: fix typo in USB strings --- firmware/apps/dfu/usb_strings.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/apps/dfu/usb_strings.txt b/firmware/apps/dfu/usb_strings.txt index bdf20486..8a4facb2 100644 --- a/firmware/apps/dfu/usb_strings.txt +++ b/firmware/apps/dfu/usb_strings.txt @@ -1,5 +1,5 @@ sysmocom - s.f.m.c. GmbH SIMtrace 2 compatible device -DFU (Device Firmare Upgrade) +DFU (Device Firmware Upgrade) RAM Flash (Application Partition) From 4814b15bbfe948d1365d2f6b5090103c9e1874c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 24 Jun 2018 11:30:31 +0200 Subject: [PATCH 23/30] SIMtrace: only enable main sniffing mode on SIMtrace board --- firmware/libboard/simtrace/include/board.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index 8e832ddb..691dbc3e 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -111,8 +111,8 @@ /* SIMtrace board supports sniffer mode */ #define HAVE_SNIFFER /* SIMtrace board supports CCID mode */ -#define HAVE_CCID +//#define HAVE_CCID /* SIMtrace board supports card emulation mode */ -#define HAVE_CARDEM +//#define HAVE_CARDEM /* SIMtrace board supports man-in-the-middle mode */ //#define HAVE_MITM From 42af4949a71b10c91548113632d08eb2b989fd2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sun, 24 Jun 2018 11:31:36 +0200 Subject: [PATCH 24/30] SIMtrace: fix default SIM_RST pin state to allow phone controlled reset --- firmware/libboard/simtrace/include/board.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index 691dbc3e..c5f4dc47 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -66,8 +66,10 @@ #define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} /* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */ #define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF +/* Card RST reset signal input (use as input since the phone will drive it) */ +#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} /* Pins used to sniff phone-card communication */ -#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST +#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF /* Disable power converter 4.5-6V to 3.3V (active high) */ #define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} /* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */ From f908f659fc1f0a05b61c4a5fe23b2bcdb2a66c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 25 Jun 2018 15:49:28 +0200 Subject: [PATCH 25/30] SIMtrace: enable interrupt on edge dection for SIM_RST pin to reset the sniffer ISO state --- firmware/libboard/simtrace/include/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h index c5f4dc47..891ab330 100644 --- a/firmware/libboard/simtrace/include/board.h +++ b/firmware/libboard/simtrace/include/board.h @@ -67,7 +67,7 @@ /* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */ #define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF /* Card RST reset signal input (use as input since the phone will drive it) */ -#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} +#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE} /* Pins used to sniff phone-card communication */ #define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF /* Disable power converter 4.5-6V to 3.3V (active high) */ From 2bac56494f97267fd36622f75cbf0887fb043a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 25 Jun 2018 15:53:19 +0200 Subject: [PATCH 26/30] ISO7816: change update_fidi to use provided USART, and disable write protection for USART register if required --- firmware/libcommon/include/simtrace.h | 6 +++- firmware/libcommon/source/simtrace_iso7816.c | 29 ++++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/firmware/libcommon/include/simtrace.h b/firmware/libcommon/include/simtrace.h index 278d5d22..3dfefe4e 100644 --- a/firmware/libcommon/include/simtrace.h +++ b/firmware/libcommon/include/simtrace.h @@ -77,7 +77,11 @@ typedef struct { extern const USBConfigurationDescriptor *configurationDescriptorsArr[]; -void update_fidi(uint8_t fidi); +/*! Update USART baud rate to Fi/Di ratio + * @param[io] usart USART peripheral base address + * @param[in] fidi FiDi value as provided in TA interface byte + */ +void update_fidi(Usart *usart, uint8_t fidi); void ISR_PhoneRST( const Pin *pPin); diff --git a/firmware/libcommon/source/simtrace_iso7816.c b/firmware/libcommon/source/simtrace_iso7816.c index 81ae9806..3d843a7c 100644 --- a/firmware/libcommon/source/simtrace_iso7816.c +++ b/firmware/libcommon/source/simtrace_iso7816.c @@ -116,20 +116,27 @@ void mode_trace_usart1_irq(void) } /* FIDI update functions */ -void update_fidi(uint8_t fidi) +void update_fidi(Usart *usart, uint8_t fidi) { - int rc; + if (NULL==usart) { + return; + } uint8_t fi = fidi >> 4; uint8_t di = fidi & 0xf; + int ratio = compute_fidi_ratio(fi, di); - rc = compute_fidi_ratio(fi, di); - if (rc > 0 && rc < 0x400) { - TRACE_INFO("computed Fi(%u) Di(%u) ratio: %d", fi, di, rc); - /* make sure UART uses new F/D ratio */ - USART_PHONE->US_CR |= US_CR_RXDIS | US_CR_RSTRX; - USART_PHONE->US_FIDI = rc & 0x3ff; - USART_PHONE->US_CR |= US_CR_RXEN | US_CR_STTTO; - } else - TRACE_INFO("computed FiDi ratio %d unsupported", rc); + if (ratio > 0 && ratio < 0x8000) { + /* make sure USART uses new F/D ratio */ + usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX; + /* disable write protection */ + if (usart->US_WPMR) { + usart->US_WPMR = US_WPMR_WPKEY(0x555341); + } + usart->US_FIDI = (ratio & 0x7ff); + usart->US_CR |= US_CR_RXEN | US_CR_STTTO; + TRACE_INFO("updated USART Fi(%u)/Di(%u) ratio(%d): %u\n\r", fi, di, ratio, usart->US_FIDI); + } else { + TRACE_WARNING("computed Fi/Di ratio %d unsupported\n\r", ratio); + } } From 67e181fb157b6d8e2a8217898aa3b5265523c940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 25 Jun 2018 15:55:33 +0200 Subject: [PATCH 27/30] console: use buffer and interrupts instead of busy loops for UART debug output --- .../libboard/common/include/board_common.h | 10 +++- .../libboard/common/source/uart_console.c | 55 +++++++++++++++---- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/firmware/libboard/common/include/board_common.h b/firmware/libboard/common/include/board_common.h index f2314ced..27f74097 100644 --- a/firmware/libboard/common/include/board_common.h +++ b/firmware/libboard/common/include/board_common.h @@ -65,10 +65,14 @@ /** UART0 */ /** Console baudrate always using 115200. */ #define CONSOLE_BAUDRATE 115200 -/** Usart Hw interface used by the console (UART0). */ -#define CONSOLE_USART UART0 -/** Usart Hw ID used by the console (UART0). */ +/** UART peripheral used by the console (UART0). */ +#define CONSOLE_UART UART0 +/** UART peripheral ID used by the console (UART0). */ #define CONSOLE_ID ID_UART0 +/** UART ISR used by the console (UART0). */ +#define CONSOLE_ISR UART0_IrqHandler +/** UART IRQ used by the console (UART0). */ +#define CONSOLE_IRQ UART0_IRQn /** Pins description corresponding to Rxd,Txd, (UART pins) */ #define CONSOLE_PINS {PINS_UART} diff --git a/firmware/libboard/common/source/uart_console.c b/firmware/libboard/common/source/uart_console.c index 2fda8ba6..e52cd514 100644 --- a/firmware/libboard/common/source/uart_console.c +++ b/firmware/libboard/common/source/uart_console.c @@ -43,6 +43,8 @@ #include #include +#include "ringbuffer.h" + /*---------------------------------------------------------------------------- * Definitions *----------------------------------------------------------------------------*/ @@ -52,7 +54,9 @@ *----------------------------------------------------------------------------*/ /** Is Console Initialized. */ -static uint8_t _ucIsConsoleInitialized=0 ; +static uint8_t _ucIsConsoleInitialized=0; +/** Ring buffer to queue data to be sent */ +static ringbuf uart_tx_buffer; /** * \brief Configures an USART peripheral with the specified parameters. @@ -63,7 +67,7 @@ static uint8_t _ucIsConsoleInitialized=0 ; extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) { const Pin pPins[] = CONSOLE_PINS; - Uart *pUart = CONSOLE_USART; + Uart *pUart = CONSOLE_UART; /* Configure PIO */ PIO_Configure(pPins, PIO_LISTSIZE(pPins)); @@ -85,12 +89,34 @@ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) /* Disable PDC channel */ pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; + /* Reset transmit ring buffer */ + rbuf_reset(&uart_tx_buffer); + + /* Enable TX interrupts */ + pUart->UART_IER = UART_IER_TXRDY; + NVIC_EnableIRQ(CONSOLE_IRQ); + /* Enable receiver and transmitter */ pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; + /* Remember the configuration is complete */ _ucIsConsoleInitialized=1 ; } +/** Interrupt Service routine to transmit queued data */ +void CONSOLE_ISR(void) +{ + Uart *uart = CONSOLE_UART; + if (uart->UART_SR & UART_SR_TXRDY) { + if (!rbuf_is_empty(&uart_tx_buffer)) { + //uart->UART_IER = UART_IER_TXRDY; + uart->UART_THR = rbuf_read(&uart_tx_buffer); + } else { + uart->UART_IDR = UART_IER_TXRDY; + } + } +} + /** * \brief Outputs a character on the UART line. * @@ -99,19 +125,28 @@ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) */ extern void UART_PutChar( uint8_t c ) { - Uart *pUart=CONSOLE_USART ; + Uart *pUart = CONSOLE_UART ; + /* Initialize console is not already done */ if ( !_ucIsConsoleInitialized ) { UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); } - /* Wait for the transmitter to be ready */ - while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ; - - /* Send character */ - pUart->UART_THR=c ; + /* Wait until there is space in the buffer */ + while (rbuf_is_full(&uart_tx_buffer)) { + if (pUart->UART_SR & UART_SR_TXEMPTY) { + pUart->UART_IER = UART_IER_TXRDY; + CONSOLE_ISR(); + } + } + /* Put character into buffer */ + rbuf_write(&uart_tx_buffer, c); + if (pUart->UART_SR & UART_SR_TXEMPTY) { + pUart->UART_IER = UART_IER_TXRDY; + CONSOLE_ISR(); + } } /** @@ -122,7 +157,7 @@ extern void UART_PutChar( uint8_t c ) */ extern uint32_t UART_GetChar( void ) { - Uart *pUart=CONSOLE_USART ; + Uart *pUart = CONSOLE_UART ; if ( !_ucIsConsoleInitialized ) { @@ -142,7 +177,7 @@ extern uint32_t UART_GetChar( void ) */ extern uint32_t UART_IsRxReady( void ) { - Uart *pUart=CONSOLE_USART ; + Uart *pUart = CONSOLE_UART; if ( !_ucIsConsoleInitialized ) { From 0aafbac7eb8f59f072d2af4c2fe88c63d265e351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 25 Jun 2018 15:56:33 +0200 Subject: [PATCH 28/30] ring buffer: increase buffer size from 128 to 256 to cope with large debug output --- firmware/libcommon/include/ringbuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/libcommon/include/ringbuffer.h b/firmware/libcommon/include/ringbuffer.h index 801e96b5..1d297604 100644 --- a/firmware/libcommon/include/ringbuffer.h +++ b/firmware/libcommon/include/ringbuffer.h @@ -5,7 +5,7 @@ #include #include -#define RING_BUFLEN 128 +#define RING_BUFLEN 256 typedef struct ringbuf { uint8_t buf[RING_BUFLEN]; From 8643420daacc8efa440e17deae6d0f86bc9004e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 25 Jun 2018 15:57:44 +0200 Subject: [PATCH 29/30] trace: increase watchdog for 500 to 2000 ms to provide more time handling buffered data --- firmware/apps/trace/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c index e705a17e..3dcbde15 100644 --- a/firmware/apps/trace/main.c +++ b/firmware/apps/trace/main.c @@ -40,7 +40,7 @@ typedef struct { void (*exit) (void); /* main loop content for given configuration */ void (*run) (void); - /* Interrupt handler for USART1 */ + /* Interrupt handler for USART0 */ void (*usart0_irq) (void); /* Interrupt handler for USART1 */ void (*usart1_irq) (void); @@ -148,9 +148,9 @@ extern int main(void) led_init(); led_blink(LED_RED, BLINK_3O_5F); - /* Enable watchdog for 500ms, with no window */ + /* Enable watchdog for 2000 ms, with no window */ WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | - (WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500)); + (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000)); PIO_InitializeInterrupts(0); From a484b02271af29d4a99f04aaaa7dbdbda95fe13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Mon, 25 Jun 2018 16:00:33 +0200 Subject: [PATCH 30/30] sniffer: use ISR to store sniffed data in buffer, add ATR and PPS parsing, and PPS related FiDi update --- firmware/libcommon/source/sniffer.c | 381 ++++++++++++++++++++++++++-- 1 file changed, 363 insertions(+), 18 deletions(-) diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c index 987e3e51..c71c4918 100644 --- a/firmware/libcommon/source/sniffer.c +++ b/firmware/libcommon/source/sniffer.c @@ -17,8 +17,10 @@ * along with this program. If not, see . * */ -/* This code implement the Sniffer mode to sniff the communication between a SIM card and a phone. +/* This code implement the Sniffer mode to sniff the communication between a SIM card (or any ISO 7816 smart card) and a phone (or any ISO 7816 card reader). * For historical reasons (i.e. SIMtrace hardware) the USART peripheral connected to the SIM card is used. + * TODO handle RST, PTS, and send data over USB + * TODO put common ISO7816-3 code is separate library (and combine clean with iso7816_4) */ #include "board.h" #include "simtrace.h" @@ -30,19 +32,22 @@ *------------------------------------------------------------------------------*/ #include +#include "utils.h" +#include "iso7816_fidi.h" /*------------------------------------------------------------------------------ * Internal definitions *------------------------------------------------------------------------------*/ -/** Maximum ucSize in bytes of the smartcard answer to a command.*/ -#define MAX_ANSWER_SIZE 10 - -/*! Maximum Answer-To-Reset (ATR) size in bytes ucSize in bytes +/*! Maximum Answer-To-Reset (ATR) size in bytes * @note defined in ISO/IEC 7816-3:2006(E) section 8.2.1 as 32, on top the initial character TS of section 8.1 * @remark technical there is no size limitation since Yi present in T0,TDi will indicate if more interface bytes are present, including TDi+i */ #define MAX_ATR_SIZE 33 +/*! Maximum Protocol and Parameters Selection (PPS) size in bytes + * @note defined in ISO/IEC 7816-3:2006(E) section 9.2 + */ +#define MAX_PPS_SIZE 6 /*! ISO 7816-3 states relevant to the sniff mode */ enum iso7816_3_sniff_state { @@ -51,7 +56,9 @@ enum iso7816_3_sniff_state { ISO7816_S_IN_ATR, /*!< while we are receiving the ATR */ ISO7816_S_WAIT_APDU, /*!< waiting for start of new APDU */ ISO7816_S_IN_APDU, /*!< inside a single APDU */ - ISO7816_S_IN_PTS, /*!< while we are inside the PTS / PSS */ + ISO7816_S_IN_PPS_REQ, /*!< while we are inside the PPS request */ + ISO7816_S_WAIT_PPS_RSP, /*!< waiting for start of the PPS response */ + ISO7816_S_IN_PPS_RSP, /*!< while we are inside the PPS request */ }; /*! Answer-To-Reset (ATR) sub-states of ISO7816_S_IN_ATR @@ -66,7 +73,18 @@ enum atr_sniff_state { ATR_S_WAIT_TD, /*!< fourth sub-group interface byte */ ATR_S_WAIT_HIST, /*!< historical byte */ ATR_S_WAIT_TCK, /*!< check byte */ - ATR_S_DONE, /*!< to indicated all ATR bytes have been received */ +}; + +/*! Protocol and Parameters Selection (PPS) sub-states of ISO7816_S_IN_PTS_REQ/ISO7816_S_IN_PTS_RSP + * @note defined in ISO/IEC 7816-3:2006(E) section 9 + */ +enum pps_sniff_state { + PPS_S_WAIT_PPSS, /*!< initial byte */ + PPS_S_WAIT_PPS0, /*!< format byte */ + PPS_S_WAIT_PPS1, /*!< first parameter byte */ + PPS_S_WAIT_PPS2, /*!< second parameter byte */ + PPS_S_WAIT_PPS3, /*!< third parameter byte */ + PPS_S_WAIT_PCK, /*!< check byte */ }; /*------------------------------------------------------------------------------ @@ -77,36 +95,328 @@ enum atr_sniff_state { * to support a second sniffer interface the code should be restructured to use handles. */ /* Pin configurations */ -/* Pin configuration to sniff communication (using USART connection card) */ +/*! Pin configuration to sniff communication (using USART connection card) */ static const Pin pins_sniff[] = { PINS_SIM_SNIFF }; +/*! Pin configuration to interconnect phone and card using the bus switch */ static const Pin pins_bus[] = { PINS_BUS_SNIFF }; +/*! Pin configuration to power the card by the phone */ static const Pin pins_power[] = { PINS_PWR_SNIFF }; +/*! Pin configuration for timer counter to measure ETU timing */ static const Pin pins_tc[] = { PINS_TC }; +/*! Pin configuration for card reset line */ +static const Pin pin_rst = PIN_SIM_RST_SNIFF; + /* USART related variables */ -/* USART peripheral used to sniff communication */ +/*! USART peripheral used to sniff communication */ static struct Usart_info sniff_usart = { .base = USART_SIM, .id = ID_USART_SIM, .state = USART_RCV, }; -/* Ring buffer to store sniffer communication data */ +/*! Ring buffer to store sniffer communication data */ static struct ringbuf sniff_buffer; +/* ISO 7816 variables */ +/*! ISO 7816-3 state */ +enum iso7816_3_sniff_state iso_state = ISO7816_S_RESET; +/*! ATR state */ +enum atr_sniff_state atr_state; +/*! ATR data + * @remark can be used to check later protocol changes + */ +uint8_t atr[MAX_ATR_SIZE]; +/*! Current index in the ATR data */ +uint8_t atr_i = 0; +/*! If convention conversion is needed */ +bool convention_convert = false; +/*! The supported T protocols */ +uint16_t t_protocol_support = 0; +/*! PPS state + * @remark it is shared between request and response since they aren't simultaneous but follow the same procedure + */ +enum pps_sniff_state pps_state; +/*! PPS request data + * @remark can be used to check PPS response + */ +uint8_t pps_req[MAX_PPS_SIZE]; +/*! PPS response data */ +uint8_t pps_rsp[MAX_PPS_SIZE]; + /*------------------------------------------------------------------------------ * Internal functions *------------------------------------------------------------------------------*/ +/*! Convert data between direct and inverse convention + * @note direct convention is LSb first and HIGH=1; inverse conversion in MSb first and LOW=1 + * @remark use a look up table to speed up conversion + */ +static const uint8_t convention_convert_lut[256] = { 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f, 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07, 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b, 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03, 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d, 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05, 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09, 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01, 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e, 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06, 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a, 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02, 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c, 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04, 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08, 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00, }; + +/*! Update the ISO 7816-3 state + * @param[in] iso_state_new new ISO 7816-3 state to update to + */ +static void change_state(enum iso7816_3_sniff_state iso_state_new) +{ + /* sanity check */ + if (iso_state_new==iso_state) { + TRACE_WARNING("Already in ISO 7816 state %u\n\r", iso_state); + return; + } + + /* handle actions to perform when switching state */ + switch (iso_state_new) { + case ISO7816_S_RESET: + update_fidi(sniff_usart.base, 0x11); /* reset baud rate to default Di/Fi values */ + // TODO disable USART and TC + break; + case ISO7816_S_WAIT_ATR: + rbuf_reset(&sniff_buffer); /* reset buffer for new communication */ + // TODO enable USART and TC + break; + case ISO7816_S_IN_ATR: + atr_i = 0; + convention_convert = false; + t_protocol_support = 0; + atr_state = ATR_S_WAIT_TS; + break; + case ISO7816_S_IN_PPS_REQ: + case ISO7816_S_IN_PPS_RSP: + pps_state = PPS_S_WAIT_PPSS; + break; + default: + break; + } + + /* save new state */ + iso_state = iso_state_new; + TRACE_INFO("Changed to ISO 7816-3 state %u\n\r", iso_state); +} + +/*! Process ATR byte + * @param[in] byte ATR byte to process + */ +static void process_byte_atr(uint8_t byte) +{ + static uint8_t atr_hist_len = 0; /* store the number of expected historical bytes */ + static uint8_t y = 0; /* last mask of the upcoming TA, TB, TC, TD interface bytes */ + + /* sanity check */ + if (ISO7816_S_IN_ATR!=iso_state) { + TRACE_ERROR("Processing ATR data in wrong ISO 7816-3 state %u\n\r", iso_state); + return; + } + if (atr_i>=ARRAY_SIZE(atr)) { + TRACE_WARNING("ATR data overflow\n\r"); + return; + } + + /* save data for use by other functions */ + atr[atr_i++] = byte; + + /* handle ATR byte depending on current state */ + switch (atr_state) { + case ATR_S_WAIT_TS: /* see ISO/IEC 7816-3:2006 section 8.1 */ + switch (byte) { + case 0x23: /* direct convention used, but decoded using inverse convention (a parity error should also have occurred) */ + case 0x30: /* inverse convention used, but decoded using direct convention (a parity error should also have occurred) */ + convention_convert = !convention_convert; + case 0x3b: /* direct convention used and correctly decoded */ + case 0x3f: /* inverse convention used and correctly decoded */ + atr_state = ATR_S_WAIT_T0; /* wait for format byte */ + break; + default: + atr_i--; /* revert last byte */ + TRACE_WARNING("Invalid TS received\n\r"); + } + break; + case ATR_S_WAIT_T0: /* see ISO/IEC 7816-3:2006 section 8.2.2 */ + case ATR_S_WAIT_TD: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ + if (ATR_S_WAIT_T0==atr_state) { + atr_hist_len = (byte&0x0f); /* save the number of historical bytes */ + } else if (ATR_S_WAIT_TD==atr_state) { + t_protocol_support |= (1<<(byte&0x0f)); /* remember supported protocol to know if TCK will be present */ + } + y = (byte&0xf0); /* remember upcoming interface bytes */ + if (y&0x10) { + atr_state = ATR_S_WAIT_TA; /* wait for interface byte TA */ + break; + } + case ATR_S_WAIT_TA: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ + if (y&0x20) { + atr_state = ATR_S_WAIT_TB; /* wait for interface byte TB */ + break; + } + case ATR_S_WAIT_TB: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ + if (y&0x40) { + atr_state = ATR_S_WAIT_TC; /* wait for interface byte TC */ + break; + } + case ATR_S_WAIT_TC: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ + if (y&0x80) { + atr_state = ATR_S_WAIT_TD; /* wait for interface byte TD */ + break; + } else if (atr_hist_len) { + atr_state = ATR_S_WAIT_HIST; /* wait for historical bytes */ + break; + } + case ATR_S_WAIT_HIST: /* see ISO/IEC 7816-3:2006 section 8.2.4 */ + if (atr_hist_len) { + atr_hist_len--; + } + if (0==atr_hist_len) { + if (t_protocol_support>1) { + atr_state = ATR_S_WAIT_TCK; /* wait for check bytes */ + break; + } + } else { + break; + } + case ATR_S_WAIT_TCK: /* see ISO/IEC 7816-3:2006 section 8.2.5 */ + /* we could verify the checksum, but we are just here to sniff */ + change_state(ISO7816_S_WAIT_APDU); /* go to next state */ + break; + default: + TRACE_INFO("Unknown ATR state %u\n\r", atr_state); + } +} + +static void process_byte_pps(uint8_t byte) +{ + uint8_t *pps_cur; /* current PPS (request or response) */ + + /* sanity check */ + if (ISO7816_S_IN_PPS_REQ==iso_state) { + pps_cur = pps_req; + } else if (ISO7816_S_IN_PPS_RSP==iso_state) { + pps_cur = pps_rsp; + } else { + TRACE_ERROR("Processing PPS data in wrong ISO 7816-3 state %u\n\r", iso_state); + return; + } + + /* handle PPS byte depending on current state */ + switch (pps_state) { /* see ISO/IEC 7816-3:2006 section 9.2 */ + case PPS_S_WAIT_PPSS: /*!< initial byte */ + if (0xff) { + pps_cur[0] = byte; + pps_state = PPS_S_WAIT_PPS0; /* go to next state */ + } else { + TRACE_INFO("Invalid PPSS received\n\r"); + change_state(ISO7816_S_WAIT_APDU); /* go back to APDU state */ + } + break; + case PPS_S_WAIT_PPS0: /*!< format byte */ + pps_cur[1] = byte; + if (pps_cur[1]&0x10) { + pps_state = PPS_S_WAIT_PPS1; /* go to next state */ + break; + } + case PPS_S_WAIT_PPS1: /*!< first parameter byte */ + pps_cur[2] = byte; /* not always right but doesn't affect the process */ + if (pps_cur[1]&0x20) { + pps_state = PPS_S_WAIT_PPS2; /* go to next state */ + break; + } + case PPS_S_WAIT_PPS2: /*!< second parameter byte */ + pps_cur[3] = byte; /* not always right but doesn't affect the process */ + if (pps_cur[1]&0x40) { + pps_state = PPS_S_WAIT_PPS3; /* go to next state */ + break; + } + case PPS_S_WAIT_PPS3: /*!< third parameter byte */ + pps_cur[4] = byte; /* not always right but doesn't affect the process */ + pps_state = PPS_S_WAIT_PCK; /* go to next state */ + break; + case PPS_S_WAIT_PCK: /*!< check byte */ + pps_cur[5] = byte; /* not always right but doesn't affect the process */ + /* verify the checksum */ + uint8_t check = 0; + check ^= pps_cur[0]; + check ^= pps_cur[1]; + if (pps_cur[1]&0x10) { + check ^= pps_cur[2]; + } + if (pps_cur[1]&0x20) { + check ^= pps_cur[3]; + } + if (pps_cur[1]&0x40) { + check ^= pps_cur[4]; + } + check ^= pps_cur[5]; + if (ISO7816_S_IN_PPS_REQ==iso_state) { + if (0==check) { /* checksum is valid */ + change_state(ISO7816_S_WAIT_PPS_RSP); /* go to next state */ + } else { /* checksum is invalid */ + change_state(ISO7816_S_WAIT_APDU); /* go to next state */ + } + } else if (ISO7816_S_IN_PPS_RSP==iso_state) { + if (0==check) { /* checksum is valid */ + uint8_t fn, dn; + if (pps_cur[1]&0x10) { + fn = (pps_cur[2]>>4); + dn = (pps_cur[2]&0x0f); + } else { + fn = 1; + dn = 1; + } + TRACE_INFO("PPS negotiation successful: Fn=%u Dn=%u\n\r", fn, dn); + update_fidi(sniff_usart.base, pps_cur[2]); + rbuf_reset(&sniff_buffer); /* reset buffer for new communication */ + } else { /* checksum is invalid */ + TRACE_INFO("PPS negotiation failed\n\r"); + } + change_state(ISO7816_S_WAIT_APDU); /* co to next state */ + } + break; + default: + TRACE_INFO("Unknown PPS state %u\n\r", pps_state); + } +} + +static void process_byte_apdu(uint8_t byte) +{ +} + static void check_sniffed_data(void) { - /* Display sniffed data */ + /* Handle sniffed data */ while (!rbuf_is_empty(&sniff_buffer)) { uint8_t byte = rbuf_read(&sniff_buffer); - TRACE_INFO_WP("0x%02x ", byte); + TRACE_WARNING_WP("< 0x%02x\n\r", byte); + switch (iso_state) { /* Handle byte depending on state */ + case ISO7816_S_RESET: /* During reset we shouldn't receive any data */ + break; + case ISO7816_S_WAIT_ATR: /* After a reset we expect the ATR */ + change_state(ISO7816_S_IN_ATR); /* go to next state */ + case ISO7816_S_IN_ATR: /* More ATR data incoming */ + process_byte_atr(byte); + break; + case ISO7816_S_WAIT_APDU: /* After the ATR we expect APDU or PPS data */ + case ISO7816_S_WAIT_PPS_RSP: + if (byte == 0xff) { + if (ISO7816_S_WAIT_PPS_RSP==iso_state) { + change_state(ISO7816_S_IN_PPS_RSP); /* Go to PPS state */ + } else { + change_state(ISO7816_S_IN_PPS_REQ); /* Go to PPS state */ + } + process_byte_pps(byte); + break; + } + case ISO7816_S_IN_APDU: /* More APDU data incoming */ + process_byte_apdu(byte); + break; + case ISO7816_S_IN_PPS_REQ: + case ISO7816_S_IN_PPS_RSP: + process_byte_pps(byte); + break; + default: + TRACE_ERROR("Data received in unknown state %u\n\r", iso_state); + } } } /*! Interrupt Service Routine called on USART activity */ -void Sniffer_usart_irq(void) +void Sniffer_usart_isr(void) { /* Read channel status register */ uint32_t csr = sniff_usart.base->US_CSR & sniff_usart.base->US_IMR; @@ -114,11 +424,36 @@ void Sniffer_usart_irq(void) if (csr & US_CSR_RXRDY) { /* Read communication data byte between phone and SIM */ uint8_t byte = sniff_usart.base->US_RHR; + /* Convert convention if required */ + if (convention_convert) { + byte = convention_convert_lut[byte]; + } /* Store sniffed data into buffer (also clear interrupt */ rbuf_write(&sniff_buffer, byte); } } +/** PIO interrupt service routine to checks if the card reset line has changed + */ +static void Sniffer_reset_isr(const Pin* pPin) +{ + /* Ensure an edge on the reset pin cause the interrupt */ + if (pPin->id!=pin_rst.id || 0==(pPin->mask&pin_rst.mask)) { + TRACE_ERROR("Pin other than reset caused a interrupt\n\r"); + return; + } + /* Update the ISO state according to the reset change */ + if (PIO_Get(&pin_rst)) { + if (ISO7816_S_WAIT_ATR!=iso_state) { + change_state(ISO7816_S_WAIT_ATR); + } + } else { + if (ISO7816_S_RESET!=iso_state) { + change_state(ISO7816_S_RESET); + } + } +} + /*------------------------------------------------------------------------------ * Global functions *------------------------------------------------------------------------------*/ @@ -126,14 +461,14 @@ void Sniffer_usart_irq(void) void Sniffer_usart1_irq(void) { if (ID_USART1==sniff_usart.id) { - Sniffer_usart_irq(); + Sniffer_usart_isr(); } } void Sniffer_usart0_irq(void) { if (ID_USART0==sniff_usart.id) { - Sniffer_usart_irq(); + Sniffer_usart_isr(); } } @@ -153,8 +488,9 @@ void Sniffer_exit(void) TRACE_INFO("Sniffer exit\n\r"); USART_DisableIt(sniff_usart.base, US_IER_RXRDY); /* NOTE: don't forget to set the IRQ according to the USART peripheral used */ - NVIC_DisableIRQ(USART0_IRQn); + NVIC_DisableIRQ(IRQ_USART_SIM); USART_SetReceiverEnabled(sniff_usart.base, 0); + } /* called when *Sniffer* configuration is set by host */ @@ -168,6 +504,12 @@ void Sniffer_init(void) PIO_Configure(pins_bus, PIO_LISTSIZE(pins_bus)); /* Configure pins to forward phone power to card */ PIO_Configure(pins_power, PIO_LISTSIZE(pins_power)); + /* Enable interrupts on port with reset line */ + NVIC_EnableIRQ(PIOA_IRQn); /* CAUTION this needs to match to the correct port */ + /* Register ISR to handle card reset change */ + PIO_ConfigureIt(&pin_rst, &Sniffer_reset_isr); + /* Enable interrupt on card reset pin */ + PIO_EnableIt(&pin_rst); /* Clear ring buffer containing the sniffed data */ rbuf_reset(&sniff_buffer); @@ -180,10 +522,13 @@ void Sniffer_init(void) /* Enable interrupt requests for the USART peripheral */ NVIC_EnableIRQ(IRQ_USART_SIM); - /* TODO configure RST pin ISR */ + /* Reset state */ + if (ISO7816_S_RESET!=iso_state) { + change_state(ISO7816_S_RESET); + } } -/* main (idle/busy) loop of this USB configuration */ +/* Main (idle/busy) loop of this USB configuration */ void Sniffer_run(void) { check_sniffed_data();