用 ST-Link 自制 GnuK
Table of contents
写得没那么详细,自求多福吧!
本文较老且杂乱,推荐结合阅读其他网友总结的版本。要说有什么特别的就是搞明白了怎么自己添加按钮、如何升级既有key的固件。
- 仓库地址:
https://salsa.debian.org/gnuk-team/gnuk/gnuk
- 支持STM32F103,STM32L432
- 使用文档:
https://www.fsij.org/doc-gnuk/index.html
- 本文基于 GnuK 分支
STABLE-BRANCH-1-2
(57fdadf)
介绍¶
GnuK 是一款开源的 USB PGP 智能卡,可以用来(相对更安全地)在不同的计算机上使用自己的 PGP 私钥。 本文将介绍如何将 ST-Link 的仿品、ST-Dongle 改造成 GnuK,并按原生的方式添加 确认按钮(Acknowledge Button)。
目标¶
- 使用 ST-Link V2(主要是仿品)制作 GnuK
- 按 原生方法 添加 自定义的确认按钮,而非网上广为流传的补丁
- 升级既有 GnuK 的固件
环境¶
- 操作系统: Manjaro
- 软件
- Python 3.9 (PipEnv)
- GNU Arm Embedded Toolchain (10.3-2021.07)
- GnuK
STABLE-BRANCH-1-2
(57fdadf)
- ST-Link 等基于 STM32F103CxT6 的设备,经测试下列 MCU 可用
- STM32F103C8T6(ST原版可当 128K Flash 版凑合)
- STM32F103CBT6(ST原版,足量 128K Flash)
- STM32F102CBT6(常见 ST-Link V2 仿品所用 MCU 之一,没错就是F102不是F103)
- STM32GC102CBT6(貌似是中国大陆专供版,ST-Link 仿品候选 MCU 之一)
流程概要¶
- 分析和修改固件、硬件,也就是添加按钮
- 为 ST-Link 刷写固件
- 编辑 GnuK 信息
修改软硬件以添加自定义按钮¶
GnuK 较新版本是支持按钮操作的。一开始我不太会用,学习一段时间单片机后,明白了如何修改 GnuK 定义的按钮。
GnuK 通过目标版配置信息提前配置好各个 IO 的模式。其中 ST-Link 所引出的部分引脚可以作为开关信号输入。
选择合适的引脚作为按钮输入¶
根据网上流传的相关原理图,PA5(CLK)引脚可以作为一个上拉输入,因此我在 PA5 和 GND 之间焊接了一个按钮。
GnuK貌似默认把所有没用上的IO配置为内部上拉了。那么只要修改按键响应逻辑就行。
修改软件¶
首先得有一份软件吧。
git clone --recursive https://salsa.debian.org/gnuk-team/gnuk/gnuk.git gnuk
若想添加对更多开发板的支持,请分别修改src/configure
(添加配置参数),chopstx/board
(添加主板IO配置与序列号),chopstx/contrib
(添加主板序列号并配置相关功能,如按钮)。我通过此方法简单适配了下WeAct工作室的BluePill Plus。
修改确认按钮的映射,需要对 STM32 的中断线路有一定了解。按钮相关代码在chopstx/contrib/ackbtn-stm32f103.c
,我将 PA5 对应的中断线路加入其中的 switch 语句,也就换了个按钮。在文末可以找到我的补丁(适用于 57fdadf)。
Note
在新版(v2.x)上,该补丁在配合git 3-way merge功能时仍可应用。
参考命令:cd chopstx && git am -3 add-button-for-stdongle.patch
编译固件¶
接下来就基本没什么技术含量了,简单记录一下编译指令
# assuming pwd is gnuk
cd src
# recommended(?) for v1.2.19, for 2.1+, it's required by default
export kdf_do=optional
# configure once
./configure --enable-factory-reset --target=ST_DONGLE --vidpid=234b:0000 --enable-certdo
# then build
make
src/build
文件夹中的 gnuk.bin
、 gnuk.hex
就是生成的固件。前者适用于直接适用下载器从对应基地址下载。
后者更适合用于调试器调试。
刷写固件¶
方法一:使用调试器¶
STM32F1x 怎么用调试器写入固件我就不说了,很多方法啊。ST-Link、JLink、CMSIS-DAP、BlackMagic Probe、UART DFU,etc.。
我用BlackMagic Probe,可以参考BMP 的 Wiki。总之我很喜欢这个调试器,GDB 深度整合,软件依赖很少,安利一下。
在修改这篇文章时,我发现了这篇文章,对初次接触 GnuK 的朋友有很大参考价值,推荐阅读。
方法二:使用升级软件升级旧的 GnuK¶
Danger
此步骤会永久性地抹除旧 GnuK 上的密钥,请三思而后行!
Note
v2.1 开始,RSA支持被移除,也因此从旧版(v1.2.x)升级至2.x需要使用旧版的脚本(旧版升级时用到了RSA验证)。经测试仍然可以使用新版的编译产物(gnuk.bin,regnual.bin)。不过保险起见,建议确保升级脚本、regnual.bin、当前固件三者版本相同。 参考报错内容(从v1.2.20升级至v2.2):
$ python upgrade_by_passwd.py
Admin password:
Device:
Configuration: 1
Interface: 0
../regnual/regnual.bin: 4728
../src/build/gnuk.bin: 96256
CRC32: e7b26341
Device:
Configuration: 1
Interface: 0
Traceback (most recent call last):
File "/gnuk-build/gnuk/tool/upgrade_by_passwd.py", line 171, in <module>
main(wait_e, passwd, data_regnual, data_upgrade[4096:])
File "/gnuk-build/gnuk/tool/upgrade_by_passwd.py", line 66, in main
gnuk.cmd_external_authenticate()
File "/gnuk-build/gnuk/tool/gnuk_token.py", line 477, in cmd_external_authenticate
raise ValueError("%02x%02x" % (sw[0], sw[1]))
ValueError: 6985
这需要用到随 GnuK 一起分发的 regnual
(reGNUal,real+GNU)。由于相关升级程序使用到了 Python,请自行补足依赖。对于使用 Pipenv 的用户,可以使用文末附件中的 Pipfile
重建环境。这里记录一下升级操作。当然也可以参考这两篇我参考的原始材料:official doc、Remy’s tutorial。
cd gnuk
cd regnual
# 在此之前需确保执行过一遍src里的configure
make
cd ../tool
# 先把 pgp agent 干掉,避免冲突
gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
# 运行升级脚本
python upgrade_by_passwd.py
# 根据提示完成接下来的操作
# 可能需要输入管理员密码,然后等待更新结束
# 若key为出厂设置,可以用 -f 避免输入密码
# python upgrade_by_passwd.py -f
# 如果平台名称发生了变化(主要在适配新平台时),需要改用下面这句,具体看脚本源码
# python upgrade_by_passwd.py -s
regnual 的固件小 Bug
对于 v1.2.19,你可能需要注释掉 regnual/regnual.c:29
以消除一个类型定义冲突。
v1.2.20 修好了这个 Bug。
配置 GnuK 以启用确认按钮¶
默认情况下确认按钮是不启用的。需要进行配置。
生成或导入密钥¶
必须先有密钥,才能改密码、启用确认按钮、修改其它信息等等。
先参考官方使用文档,配置智能卡信息,生成密钥对,并写入相关信息。
一些步骤: + 在 GnuK 上生成密钥或将私钥转移到 GnuK 上; + 配置Gnuk信息(名称,称谓,语言偏好,公钥地址,密码,管理员密码,恢复密码); + 其它进阶配置;
生成密钥部分教程原本的讲得并不清楚,如果用了默认配置快速生成密钥对,则需要进入密钥编辑模式进一步修改,也就是gpg --expert --edit-key [fingerprint]
。
实际上教程里都是在修改原来的Key,同样也是gpg --expert --edit-key [fingerprint]
。
懒了,部分细节可以参考本文对应的英文文章(outdated)。
启用确认按钮¶
要装 GnuPG v2.3 或更新版本,否则没这个功能。archlinux/pacman 用户可以使用 aur/gnupg23。 现在最新版本都2.4+了,没啥限制。
然后按下面的步骤启用对应的确认按钮。
gpg --card-edit # 编辑卡信息
gpg/card> admin # 进入管理员模式
gpg/card> uif # 查看相关帮助
gpg/card> uif 1 on # 开启签名确认
gpg/card> uif 2 on # 开启解密确认
gpg/card> uif 3 on # 开启身份验证确认
gpg/card> q # quit
我个人就开了前两个确认,其它的感觉有点麻烦,开启确认是为了避免误操作和后台操作罢了。
其它说明¶
想使用全部最新功能(比如开启确认按钮),必须使用最新的开发板gnupg(2.3),下载地址在此Arch 用户可以用 aur/gnupg23
ST_DONGLE编译平台有bug,不仅用不了 Button,make clean 也清不干净,需要删除src重新构建待定问题根源,可能 flash 一定要擦除一遍才能正常使用 GnuK。- 本条写给超级小白(包括曾经的我):对于新的板子,button 可以用
AFIO_EXTICR1_EXTI0_PA
,这里用到的是外部中断,线路/中断号/管脚要匹配。有些中断号是复用的,注意一下。 - 如果 MCU 的 Flash 不够用,可以关闭部分功能、删除对部分算法的支持。有的时候 64K Flash 也可以刷 GnuK,但
reGNUal
升级程序会出现运行错误,也就不能用原生方法升级,务必注意。 - 对于
oh-my-zsh
用户,想启用 PGP+SSH,可以直接启用gnupg
插件。 - 拆 ST-Link 针脚,可以先把胶座去掉,然后一根根将针焊下来,最后配合不锈钢刮板趁热将焊盘上的锡刮干净。