Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@HappyCodingRobot
Forked from rot42/README.md
Created April 14, 2020 14:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save HappyCodingRobot/d95c988e6c8c9a74ada252195c0978a8 to your computer and use it in GitHub Desktop.
Save HappyCodingRobot/d95c988e6c8c9a74ada252195c0978a8 to your computer and use it in GitHub Desktop.
Gnuk Token on ST Dongle with STM32F103CBU6

Gnuk Token on ST Dongle with STM32F103CBU6

Based on Daniel Kucera's implementation of the confirmation button, adapted for a different ST Dongle using an STM32F103CBU6 microcontroller.

STM32F103CBU6 microcontroller ST-LINK/V2 clone dongle

Order of the 4 SWD interface holes from left to right:

  • 3.3V
  • SWCLK
  • GND
  • SWDIO

The left PINs where you can solder the confirmation button are connected as follow:

  • RST is connected to GPIO PB6.
  • SWIM is connected to GPIO PB8 and PB11.

You can use a multimeter in continuity mode and the below pinout diagram (from the STM32F103 datasheet) in order to confirm you have an ST dongle compatible with this patch.

STM32F103CBU6 pinout

Patch, build and flash the Gnuk firmware.

git clone --branch=release/1.2.14 --recurse-submodules https://salsa.debian.org/gnuk-team/gnuk/gnuk
cd gnuk
git apply ../gnuk-1.2.14-st-dongle-button.patch
cd src
./configure --vidpid=234b:0000 --enable-factory-reset --enable-confirm-button --enable-certdo --disable-sys1-compat --target=ST_DONGLE
make
openocd -f ../../stm32write.cfg

The Gnuk patch requires button confirmation for signature, encryption and authentication operations. You can comment out some calls to the wait_button function if you need button confirmation only for some of these operations.

Submodule chopstx contains untracked content
Submodule chopstx contains modified content
diff --git a/chopstx/board/board-st-dongle.h b/chopstx/board/board-st-dongle.h
index ef9b4f3..01db70b 100644
--- a/chopstx/board/board-st-dongle.h
+++ b/chopstx/board/board-st-dongle.h
@@ -5,6 +5,7 @@
#define MCU_STM32F1 1
#define STM32F10X_MD /* Medium-density device */
+
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE 9
#define STM32_HSECLK 8000000
@@ -13,7 +14,8 @@
#define GPIO_LED_SET_TO_EMIT 9
#define GPIO_USB_BASE GPIOA_BASE
#define GPIO_USB_SET_TO_ENABLE 15
-#undef GPIO_OTHER_BASE
+#define GPIO_OTHER_BASE GPIOB_BASE
+#define GPIO_OTHER_BUTTON_PIN 6
/*
* Port A setup.
@@ -30,5 +32,15 @@
#define VAL_GPIO_LED_CRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIO_LED_CRH 0x38811838 /* PA15...PA8 */
-#define RCC_ENR_IOP_EN RCC_APB2ENR_IOPAEN
-#define RCC_RSTR_IOP_RST RCC_APB2RSTR_IOPARST
+/*
+ * Port B setup.
+ * PB6 - Button RST - input with pull-high
+ * PB8 - Button SWIM - open-drain to ground 2MHz
+ * PB11 - Button SWIM - open-drain to ground 2MHz
+ */
+#define VAL_GPIO_OTHER_ODR 0xFFFF0040 /* port output */
+#define VAL_GPIO_OTHER_CRL 0x88888888 /* PB7...PB0 */
+#define VAL_GPIO_OTHER_CRH 0x88886886 /* PB15...PB8 */
+
+#define RCC_ENR_IOP_EN (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN)
+#define RCC_RSTR_IOP_RST (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST)
diff --git a/chopstx/mcu/sys-stm32f103.c b/chopstx/mcu/sys-stm32f103.c
index 2884385..c4577cc 100644
--- a/chopstx/mcu/sys-stm32f103.c
+++ b/chopstx/mcu/sys-stm32f103.c
@@ -63,6 +63,21 @@ static void wait (int count)
asm volatile ("" : : "r" (i) : "memory");
}
+void
+wait_button (void)
+{
+#if defined(GPIO_OTHER_BUTTON_PIN)
+ int tmp = 1;
+ while (tmp && GPIO_OTHER->IDR & (1 << GPIO_OTHER_BUTTON_PIN))
+ {
+ set_led(1);
+ wait(1000000);
+ tmp = GPIO_OTHER->IDR & (1 << GPIO_OTHER_BUTTON_PIN);
+ set_led(0);
+ wait(1000000);
+ }
+#endif
+}
static void
usb_lld_sys_shutdown (void)
diff --git a/chopstx/mcu/sys-stm32f103.h b/chopstx/mcu/sys-stm32f103.h
index 2492acc..0c3064a 100644
--- a/chopstx/mcu/sys-stm32f103.h
+++ b/chopstx/mcu/sys-stm32f103.h
@@ -22,6 +22,8 @@ extern const uint8_t sys_board_name[];
# define SYS_BOARD_ID BOARD_ID
#endif
+void wait_button (void);
+
typedef void (*handler)(void);
typedef void (*nonreturn_handler0)(void)__attribute__((noreturn));
typedef void (*nonreturn_handler1)(void *)__attribute__((noreturn));
diff --git a/src/config.h.in b/src/config.h.in
index cee4dcd..5195e63 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -10,5 +10,6 @@
@CERTDO_DEFINE@
@HID_CARD_CHANGE_DEFINE@
@LIFE_CYCLE_MANAGEMENT_DEFINE@
+@CONFIRM_BUTTON_DEFINE@
@ACKBTN_DEFINE@
@SERIALNO_STR_LEN_DEFINE@
diff --git a/src/configure b/src/configure
index d09cde6..4d4a690 100755
--- a/src/configure
+++ b/src/configure
@@ -45,6 +45,7 @@ certdo=no
hid_card_change=no
factory_reset=no
ackbtn_support=yes
+confirm_button=no
flash_override=""
# For emulation
prefix=/usr/local
@@ -102,6 +103,10 @@ for option; do
factory_reset=yes ;;
--disable-factory-reset)
factory_reset=no ;;
+ --enable-confirm-button)
+ confirm_button=yes ;;
+ --disable-confirm-button)
+ confirm_button=no ;;
--with-dfu)
with_dfu=yes ;;
--without-dfu)
@@ -151,6 +156,8 @@ Configuration:
FST_01_00 (unreleased version with 8MHz XTAL)
--enable-factory-reset
support life cycle management [no]
+ --enable-confirm-button
+ enable button to confirm requests [no]
--enable-debug debug with virtual COM port [no]
--enable-pinpad=cir
PIN entry support [no]
@@ -328,6 +335,15 @@ else
echo "Life cycle management is NOT supported"
fi
+# --enable-confirm-button option
+if test "$confirm_button" = "yes"; then
+ CONFIRM_BUTTON_DEFINE="#define CONFIRM_BUTTON_SUPPORT 1"
+ echo "Confirm button is supported"
+else
+ CONFIRM_BUTTON_DEFINE="#undef CONFIRM_BUTTON_SUPPORT"
+ echo "Confirm button is NOT supported"
+fi
+
# Acknowledge button support
if test "$ackbtn_support" = "yes"; then
ACKBTN_DEFINE="#define ACKBTN_SUPPORT 1"
@@ -517,6 +533,7 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
-e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
-e "s/@HID_CARD_CHANGE_DEFINE@/$HID_CARD_CHANGE_DEFINE/" \
-e "s/@LIFE_CYCLE_MANAGEMENT_DEFINE@/$LIFE_CYCLE_MANAGEMENT_DEFINE/" \
+ -e "s/@CONFIRM_BUTTON_DEFINE@/$CONFIRM_BUTTON_DEFINE/" \
-e "s/@ACKBTN_DEFINE@/$ACKBTN_DEFINE/" \
-e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
< config.h.in > config.h
diff --git a/src/openpgp.c b/src/openpgp.c
index f4bb37c..ae849ab 100644
--- a/src/openpgp.c
+++ b/src/openpgp.c
@@ -945,6 +945,10 @@ cmd_pso (struct eventflag *ccid_comm)
return;
}
+#ifdef CONFIRM_BUTTON_SUPPORT
+ wait_button();
+#endif
+
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING))
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
@@ -1041,6 +1045,10 @@ cmd_pso (struct eventflag *ccid_comm)
return;
}
+#ifdef CONFIRM_BUTTON_SUPPORT
+ wait_button();
+#endif
+
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION))
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
@@ -1154,6 +1162,10 @@ cmd_internal_authenticate (struct eventflag *ccid_comm)
return;
}
+#ifdef CONFIRM_BUTTON_SUPPORT
+ wait_button();
+#endif
+
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
@@ -1426,6 +1438,10 @@ cmd_get_challenge (struct eventflag *ccid_comm)
if (challenge)
random_bytes_free (challenge);
+#ifdef CONFIRM_BUTTON_SUPPORT
+ wait_button();
+#endif
+
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING)
|| gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION)
diff --git a/src/usb-ccid.c b/src/usb-ccid.c
index e76a1f3..0f26363 100644
--- a/src/usb-ccid.c
+++ b/src/usb-ccid.c
@@ -941,7 +941,6 @@ ccid_send_status (struct ccid *c)
usb_lld_write (c->epi->ep_num, ccid_reply, CCID_MSG_HEADER_SIZE);
#endif
- led_blink (LED_SHOW_STATUS);
#ifdef DEBUG_MORE
DEBUG_INFO ("St\r\n");
#endif
source [find interface/stlink-v2.cfg]
source [find target/stm32f1x.cfg]
init
stm32f1x unlock 0
reset halt
stm32f1x mass_erase 0
flash write_bank 0 build/gnuk.bin 0
stm32f1x lock 0
reset halt
exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment