Skip to content

Instantly share code, notes, and snippets.

@rot42
Last active September 8, 2020 22:26
Show Gist options
  • Save rot42/cd6ff46be45f0b7d7cd461a7bcc14d79 to your computer and use it in GitHub Desktop.
Save rot42/cd6ff46be45f0b7d7cd461a7bcc14d79 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.15 --recurse-submodules https://salsa.debian.org/gnuk-team/gnuk/gnuk
cd gnuk
git apply ../gnuk-1.2.15-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 cc49f4ef..7a32badc:
diff --git a/chopstx/board/board-st-dongle.h b/chopstx/board/board-st-dongle.h
index 19f717b..4dd567a 100644
--- a/chopstx/board/board-st-dongle.h
+++ b/chopstx/board/board-st-dongle.h
@@ -13,7 +13,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 +31,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 3430a16..6d3b42e 100644
--- a/chopstx/mcu/sys-stm32f103.c
+++ b/chopstx/mcu/sys-stm32f103.c
@@ -64,6 +64,30 @@ set_led (int on)
#endif
}
+static void wait (int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ 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 702fea2..f83e0b2 100644
--- a/chopstx/mcu/sys-stm32f103.h
+++ b/chopstx/mcu/sys-stm32f103.h
@@ -23,6 +23,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 cee4dcd7..5195e638 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 d09cde68..4d4a690c 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 f4bb37ce..ae849aba 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 e76a1f3d..0f26363e 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
reset halt
stm32f1x unlock 0
reset halt
stm32f1x mass_erase 0
flash write_bank 0 build/gnuk.bin 0
stm32f1x lock 0
reset halt
exit
@coelner
Copy link

coelner commented Aug 25, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment