[Gnuk-users] Upgrading gnuk on a nitrokey start

NIIBE Yutaka gniibe at fsij.org
Thu Aug 18 02:30:21 UTC 2016


On 08/16/2016 10:25 PM, Remy van Elst wrote:
>     Please note that we use reGNUal in teh upgrading process.  The setting
>     of permission with your USB ID is requires for reGNUal too.
> 
> 
> Even if I do it as the root user?

If it's a simple POSIX sytem, root means full privilege, that's true.

> I didn't see a specific compile option for regnual for a different
> vidpid like in gnuk's configure script.

ReGNUal shares the configuration of Gnuk proper.

> Is there a way to see which keys are currently in there? And, is it
> possible to remove those keys if they are written? Does the
> 'gnuk_remove_keys_libusb.py' also clean up those keys?

(1) No.  (2) Difficult (nobody has tried).  (3) No.

For (1), it is possible to write such a tool.  Nobody has tried that.
By using tool/gnuk_token.py and the method cmd_read_binary, it is
possible to write such a tool.

For (2), I think that it is possible to do so, or it is possible to
write such a tool, in theory.  I'm saying because I once implement the
removal feature of upgrade RSA public key in Gnuk.  Nobody has tried
that.  IIUC, it is somehow likely that this sequence would work:

./tool/gnuk_put_binary_libusb.py -k 0 /dev/null
./tool/gnuk_put_binary_libusb.py -k 1 /dev/null
./tool/gnuk_put_binary_libusb.py -k 2 /dev/null
./tool/gnuk_put_binary_libusb.py -k 3 /dev/null

Please note that this is not tested at all.


'gnuk_remove_keys_libusb.py' is a tool to remove the RSA private keys
(not RSA public key for upgrade).

> When trying the upgrade with password script, this happens:
> 
> $ sudo python2 ./upgrade_by_passwd.py -f -k 4 ../regnual/regnual.bin
> ../src/build/gnuk.bin
> ../regnual/regnual.bin: 4372
> ../src/build/gnuk.bin: 110592
> CRC32: 8d82b2df
> 
> Device:
> Configuration: 1
> Interface: 0
> Traceback (most recent call last):
>   File "./upgrade_by_passwd.py", line 130, in <module>
>     main(wait_e, keyno, passwd, data_regnual, data_upgrade[4096:])
>   File "./upgrade_by_passwd.py", line 48, in main
>     gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
>   File "/home/remy/repo/gnuk/tool/gnuk_token.py", line 288, in
> cmd_write_binary
>     raise ValueError("cmd_write_binary 1", "%02x%02x" % (sw[0], sw[1]))
> ValueError: ('cmd_write_binary 1', '6581')

-k is only valid with 0 to 3.

> $ sudo python2 ./upgrade_by_passwd.py -f -k 3 ../regnual/regnual.bin
> ../src/build/gnuk.bin
> ../regnual/regnual.bin: 4372
> ../src/build/gnuk.bin: 110592
> CRC32: 8d82b2df
> 
> Device:
> Configuration: 1
> Interface: 0
> Traceback (most recent call last):
>   File "./upgrade_by_passwd.py", line 130, in <module>
>     main(wait_e, keyno, passwd, data_regnual, data_upgrade[4096:])
>   File "./upgrade_by_passwd.py", line 48, in main
>     gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
>   File "/home/remy/repo/gnuk/tool/gnuk_token.py", line 288, in
> cmd_write_binary
>     raise ValueError("cmd_write_binary 1", "%02x%02x" % (sw[0], sw[1]))
> ValueError: ('cmd_write_binary 1', '6581')
> 
> $ sudo python2 ./upgrade_by_passwd.py -f -k 2 ../regnual/regnual.bin
> ../src/build/gnuk.bin
> ../regnual/regnual.bin: 4372
> ../src/build/gnuk.bin: 110592
> CRC32: 8d82b2df
> 
> Device:
> Configuration: 1
> Interface: 0
> Traceback (most recent call last):
>   File "./upgrade_by_passwd.py", line 130, in <module>
>     main(wait_e, keyno, passwd, data_regnual, data_upgrade[4096:])
>   File "./upgrade_by_passwd.py", line 48, in main
>     gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
>   File "/home/remy/repo/gnuk/tool/gnuk_token.py", line 288, in
> cmd_write_binary
>     raise ValueError("cmd_write_binary 1", "%02x%02x" % (sw[0], sw[1]))
> ValueError: ('cmd_write_binary 1', '6581')
> 
> 
> $ sudo python2 ./upgrade_by_passwd.py -f -k 1 ../regnual/regnual.bin
> ../src/build/gnuk.bin
> ../regnual/regnual.bin: 4372
> ../src/build/gnuk.bin: 110592
> CRC32: 8d82b2df
> 
> Device:
> Configuration: 1
> Interface: 0
> Traceback (most recent call last):
>   File "./upgrade_by_passwd.py", line 130, in <module>
>     main(wait_e, keyno, passwd, data_regnual, data_upgrade[4096:])
>   File "./upgrade_by_passwd.py", line 48, in main
>     gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
>   File "/home/remy/repo/gnuk/tool/gnuk_token.py", line 288, in
> cmd_write_binary
>     raise ValueError("cmd_write_binary 1", "%02x%02x" % (sw[0], sw[1]))
> ValueError: ('cmd_write_binary 1', '6581')

I think that it's not good to proceed after a failure.  Some failure is not
recoverable.

If those failures are real, there is no way to recover from here,
other than the (2) method I described above, which nobody has tried.

I don't know the reason why the invocation of upgrade_by_passwd.py
fails in that way.  If it had already filled by a public key, it's
possible.  If not, it's new failure mode for me.

> When I try the normal upgrade script, this is the output:
> 
> $ sudo python2 ./gnuk_upgrade.py -k
> CB1522E739DD4E26F86EBC732B58AFBDA3059107 ../regnual/regnual.bin
> ../src/build/gnuk.bin
> ../regnual/regnual.bin: 4372
> ../src/build/gnuk.bin: 110592
> CRC32: 8d82b2df

No, it's not "normal upgrade script" at all.  It was a tool for my
experiment, not useful after we have upgrade_by_passwd.py.  It is only
useful if you successfully registered a public key to Gnuk Token, and
the private counter part is under control of gpg-agent.

> Device:
> Configuration: 1
> Interface: 0
> Traceback (most recent call last):
>   File "./gnuk_upgrade.py", line 148, in <module>
>     main(keyno, keygrip, data_regnual, data_upgrade[4096:])
>   File "./gnuk_upgrade.py", line 95, in main
>     signed = gpg_sign(keygrip, binascii.hexlify(challenge))
>   File "./gnuk_upgrade.py", line 64, in gpg_sign
>     pos = signed.index("D (7:sig-val(3:rsa(1:s256:") + 26
> ValueError: substring not found

I think that there are two (or more) possibilities for this failure.

It fails because the key CB1522E739DD4E26F86EBC732B58AFBDA3059107 is
not under control of gpg-agent or it fails to sign (because of sudo).

Have you asked a passphrase for the key?

Another obvious bug (which I found now) is that it only works 50%.
If the top-bit is 1, the result will be

	D (7:sig-val(3:rsa(1:s257:...

So, it fails.

> If there is no way to see or wipe the current keys for firmware update
> via USB, is there another way to reset the token fully?

See (2) for the public key of firmware upgrade.  Please note that I
don't know this feature is supported by Nitrokey Start's build of
Gnuk.

For resetting the token fully, we need SWD debugger.
-- 



More information about the gnuk-users mailing list