Homemade GnuK with ST-Dongle

 · 5 分钟
Last updated: 2022-06-09
Table of contents



Final result


  • Convert ST-Link clones (ST-Dongle) to GnuK.
  • Add a button to the dongles and use GnuK’s built-in support for it.
  • Upgrade existing GnuK dongles.


  • OS: Manjaro
  • Software
    • Python 3.9 (PipEnv)
    • GNU Arm Embedded Toolchain (10.3-2021.07)
    • GnuK v1.2.19 STABLE-BRANCH-1-2(57fdadf)

Modify the hardware to add a button

According to related datasheets, PA5(CLK) is available as an input pulled high. So, I soldered a button between PA5(CLK) and GND. The extra reason why I choose PA5(CLK) instead of other pins is written in the next section.

Modify the source code of Gnuk

Get a copy of the code first.

git clone --recursive https://salsa.debian.org/gnuk-team/gnuk/gnuk.git gnuk

When writing this post, the latest version of Gnuk is 1.2.19, and is available at branch STABLE-BRANCH-1-2(57fdadf). I’m working on this branch in this post, so make sure you’ve checked it out.

The latest Gnuk firmware has already implemented the acknowledge button, and the only problem is to decide the pin to use. After digging around, I found the core part is a function called ackbtn_init in chopstx/contrib/ackbtn-stm32f103.c in a switch-case block, and that is what to be patched.

By reading the board definition in chopstx/board/board-st-dongle.h, I found that almost all pins from GPIO A are configured as input pulled high, and I happened to notice that the CLK(PA5) pin is right at the edge of the board. At that time, I decided to use PA5(CLK) as input pin to minimize the modification to the code.

The patch is provided as an attachment below as 0001-add-pa5-as-switch-pin-for-st-dongle.patch. Basically, it’s to choose the right hardware interrupt signal.

Build the firmware

This is quite easy since no research have to be done.

# assuming pwd is gnuk
cd src
export kdf_do=optional  # recommended(?) for v1.2.19
./configure --enable-factory-reset --target=ST_DONGLE --vidpid=234b:0000 --enable-certdo

Get gnuk.bin, gnuk.hex in src/build, these are the built firmware. The file with bin suffix is used for direct download(to a base address) or upgrading existing dongles, while the other one is easier to use with a debugger as it contains address information.

Flash the firmware

Choice 1: using the debugger

Here we need gnuk.hex.

I use Black Magic Probe as the debugger. I wrote a custom .gdbinit to automate the process, take it as an example. Note that if you cannot probe or attach to the target, enable connect_srst of the BMP.

There a lot of materials on the web about st-dongle’s pin definition and how to flash them, eg. rot42’s gist or Danman’s post.

Choice 2: upgrade existing tokens


Here we need gnuk.bin.

You might want to upgrade your existing Gnuk tokens to the latest firmware.

Go to src/regnual, and make the update helper.

cd src/regnual


For v1.2.19, you might want to comment out regnual/regnual.c:29 as a quick workaround for a typing conflict. For v1.2.20, The bug is fixed.

Now you get regnual.bin / reGNUal (the update program).

Prepare your Python virtual environment and update the firmware. The Pipfile is provided as an attachment. (BTW, the necessary packages for tests are included as well.) Then go to tool and we’ll use upgrade_by_passwd.py.


There’s a bug at line 132, change while len(sys.argv) > 1: to while len(sys.argv) > 3:.
v1.2.19 fixed the bug.

# assuming pwd is gnuk and you have the provided Pipfile here
pipenv install
cd tool
# upgrade the token
# -f means using factory passwd automaticly
# -s means ignore the target string difference
python upgrade_by_passwd.py -f ../regnual/regnual.bin ../src/build/gnuk.bin
#python upgrade_by_passwd.py -f -s ../regnual/regnual.bin ../src/build/gnuk.bin  # force

Read official doc or Remy’s tutorial for more detail.

Configure the Gnuk – Enable the Acknowledge Button

Please import your key to the card following the official documents first.

I found from the mailing list that only the latest develop version(at least v2.3?) of GnuPG supports modifiying the UIF(User Interaction Flag) on the Gnuk. It seems the feature will not be backported to v2.2(LTS release). So you have to build v2.3 and install it. Note that you have to completely replace the old 2.x version in order to avoid errors.

On Arch-like distros or distros use pacman as package manager, you can use aur package aur/gnupg23. For other distros, you are on your own.

After installing GnuPG v2.3, use the following commands to activate the button. These commands will work only if there is any key presented on the GnuK!

Assuming you’ve already imported your key to GnuK and customized it following the official documents, here are commands to enable the acknowledge button(for gnupg v2.3 and above):

gpg --card-edit
gpg/card> admin  # enter admin mode
gpg/card> uif  # show help info
gpg/card> uif 1 on  # sign
gpg/card> uif 2 on  # decrypt
gpg/card> uif 3 on  # auth
gpg/card> q  # quit



  • STM32 GPIO Setup: https://gist.github.com/iwalpola/6c36c9573fd322a268ce890a118571ca

Change log


  • Add more details
  • Fix errors
  • update gnupg 2.3 aur package link


  • minor tweaks
  • move to my own blog


  • update for Gnuk v1.2.19
  • remove file: requirements.txt
  • add file: gnuk-no-vidpid-v1.2.19-ST_DONGLE.elf
  • add file: Pipfile