mirror of
https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
synced 2024-09-21 03:10:08 +00:00
131 lines
3.7 KiB
Plaintext
131 lines
3.7 KiB
Plaintext
Firmware update feature
|
|
=======================
|
|
|
|
The firmware update feature of Gnuk is experimental. Please be
|
|
careful using that.
|
|
|
|
Note that updating firmware, all data objects and keys will be
|
|
removed. There is _no way_ to preserve those data.
|
|
|
|
|
|
Preparation
|
|
===========
|
|
|
|
In addition to settings of Gnuk, I create a file
|
|
/etc/udev/rules.d/92-gnuk.rules::
|
|
|
|
# For updating firmware, permission settings are needed.
|
|
|
|
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
|
|
ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd"
|
|
|
|
|
|
While I am a member of group "pcscd" in /etc/group.
|
|
|
|
This is needed for reGNUal, the firmware update program.
|
|
|
|
|
|
Registering a public key for firmware update
|
|
============================================
|
|
|
|
You need to register a public key to update the firmware. It should
|
|
be RSA 2048-bit.
|
|
|
|
One way to extract public key data is by using "gpg-connect-agent"
|
|
command connecting gpg-agent.
|
|
|
|
We can examine key information of gpg-agent by "KEYINFO" command.
|
|
Here is my example::
|
|
|
|
$ gpg-connect-agent "KEYINFO --list" /bye
|
|
S KEYINFO 65F67E742101C7FE6D5B33FCEFCF4F65EAF0688C T D276000124010200F517000000010000 OPENPGP.2 - - -
|
|
S KEYINFO 101DE7B639FE29F4636BDEECF442A9273AFA6565 T D276000124010200F517000000010000 OPENPGP.1 - - -
|
|
S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - -
|
|
OK
|
|
|
|
I have three keys in my token.
|
|
|
|
With the script below, I extract public key of the keygrip
|
|
5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin::
|
|
|
|
$ ./get_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
|
|
|
|
Here is the script, get_public_key.py::
|
|
|
|
#! /usr/bin/python
|
|
|
|
import sys, binascii
|
|
from subprocess import check_output
|
|
|
|
def get_gpg_public_key(keygrip):
|
|
result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"])
|
|
key = ""
|
|
while True:
|
|
i = result.find('%')
|
|
if i < 0:
|
|
key += result
|
|
break
|
|
hex_str = result[i+1:i+3]
|
|
key += result[0:i]
|
|
key += chr(int(hex_str,16))
|
|
result = result[i+3:]
|
|
|
|
pos = key.index("D (10:public-key(3:rsa(1:n257:") + 31 # skip NUL too
|
|
key = key[pos:-17] # )(1:e3:XYZ)))\nOK\n
|
|
if len(key) != 256:
|
|
raise ValueError, binascii.hexlify(key)
|
|
return key
|
|
|
|
if __name__ == '__main__':
|
|
keygrip = sys.argv[1]
|
|
k = get_gpg_public_key(keygrip)
|
|
shorthand = keygrip[0:8] + ".bin"
|
|
f = open(shorthand,"w")
|
|
f.write(k)
|
|
f.close()
|
|
|
|
|
|
Then, we can put the data of public key into token by::
|
|
|
|
$ tool/gnuk_put_binary_libusb.py -k 0 5D6C8968.bin
|
|
|
|
|
|
Invoking firmware update
|
|
========================
|
|
|
|
We specify reGNUal binary and Gnuk binary.
|
|
|
|
$ ../tool/gnuk_upgrade.py ../regnual/regnual.bin gnuk.bin
|
|
|
|
|
|
Two or more tokens
|
|
==================
|
|
|
|
Currently, GnuPG doesn't support multiple devices connected to the
|
|
host.
|
|
|
|
In order to update the firmware of a TARGET token, we use GnuPG to
|
|
authenticate with public key. It is assumed that you have another
|
|
AUTH token for this. This situation is somewhat complicated.
|
|
|
|
What I do is:
|
|
(1) Don't run PC/SC daemon::
|
|
|
|
# /etc/init.d/pcscd stop
|
|
|
|
(2) To make sure, kill scdaemon::
|
|
|
|
$ killall -9 scdaemon
|
|
|
|
(3) Insert the AUTH token to USB, and use it::
|
|
|
|
$ gpg --card-status
|
|
|
|
(4) Insert the TARGET token to USB (after scdaemon communicates AUTH
|
|
token), and invoke gnuk_upgrade.py.
|
|
In this situation, gnuk_upgrade.py tries to connect one of tokens,
|
|
but a connection to the AUTH token will fail because scdaemon is
|
|
connecting to that device, and will be expected to connect to the
|
|
TARGET token succesufully, instead.
|
|
--
|